@joebigelow / wix-1 / commits / 56105916

Fix building and perf for bundles with 1000s of package and BA payloads

Fixes other half of #5300

Sean Hall committed Jun 9, 2021 at 11:30 UTC 56105916271ff9a7c0bfa237b45b9b3fab9c570b
23 files changed +317 -186
.gitignore
+2
@@ -399,3 +399,5 @@ build/.tools/
399
400 # Ignore generated test data
401 src/test/burn/TestData/CacheTests/BundleC/fivegb.file
402 +src/test/burn/TestData/Manual/BundleB/BAPayloads
403 +src/test/burn/TestData/Manual/BundleB/PackagePayloads
src/burn/engine/apply.cpp
+1 -1
@@ -1175,7 +1175,7 @@ static HRESULT ExtractContainer(
1175 {
1176 BOOL fExtracted = FALSE;
1177
1178 - hr = PayloadFindEmbeddedBySourcePath(pContext->pPayloads, sczStreamName, &pExtract);
1178 + hr = PayloadFindEmbeddedBySourcePath(pContainer->sdhPayloads, sczStreamName, &pExtract);
1179 if (E_NOTFOUND != hr)
1180 {
1181 ExitOnFailure(hr, "Failed to find embedded payload by source path: %ls container: %ls", sczStreamName, pContainer->sczId);
src/burn/engine/burnextension.cpp
+6 -5
@@ -26,6 +26,7 @@ EXTERN_C HRESULT BurnExtensionParseFromXml(
26 IXMLDOMNodeList* pixnNodes = NULL;
27 IXMLDOMNode* pixnNode = NULL;
28 DWORD cNodes = 0;
29 + LPWSTR scz = NULL;
30
31 // Select BundleExtension nodes.
32 hr = XmlSelectNodes(pixnBundle, L"BundleExtension", &pixnNodes);
@@ -59,11 +60,11 @@ EXTERN_C HRESULT BurnExtensionParseFromXml(
60 ExitOnFailure(hr, "Failed to get @Id.");
61
62 // @EntryPayloadId
62 - hr = XmlGetAttributeEx(pixnNode, L"EntryPayloadId", &pExtension->sczEntryPayloadId);
63 - ExitOnFailure(hr, "Failed to get @EntryPayloadId.");
63 + hr = XmlGetAttributeEx(pixnNode, L"EntryPayloadSourcePath", &scz);
64 + ExitOnFailure(hr, "Failed to get @EntryPayloadSourcePath.");
65
65 - hr = PayloadFindById(pBaPayloads, pExtension->sczEntryPayloadId, &pExtension->pEntryPayload);
66 - ExitOnFailure(hr, "Failed to find BundleExtension EntryPayload '%ls'.", pExtension->sczEntryPayloadId);
66 + hr = PayloadFindEmbeddedBySourcePath(pBaPayloads->sdhPayloads, scz, &pExtension->pEntryPayload);
67 + ExitOnFailure(hr, "Failed to find BundleExtension EntryPayload '%ls'.", pExtension->sczId);
68
69 // prepare next iteration
70 ReleaseNullObject(pixnNode);
@@ -72,6 +73,7 @@ EXTERN_C HRESULT BurnExtensionParseFromXml(
73 hr = S_OK;
74
75 LExit:
76 + ReleaseStr(scz);
77 ReleaseObject(pixnNode);
78 ReleaseObject(pixnNodes);
79
@@ -92,7 +94,6 @@ EXTERN_C void BurnExtensionUninitialize(
94 {
95 BURN_EXTENSION* pExtension = &pBurnExtensions->rgExtensions[i];
96
95 - ReleaseStr(pExtension->sczEntryPayloadId);
97 ReleaseStr(pExtension->sczId);
98 }
99 MemFree(pBurnExtensions->rgExtensions);
src/burn/engine/burnextension.h
-1
@@ -13,7 +13,6 @@ typedef struct _BURN_EXTENSION_ENGINE_CONTEXT BURN_EXTENSION_ENGINE_CONTEXT;
13
14 typedef struct _BURN_EXTENSION
15 {
16 - LPWSTR sczEntryPayloadId;
16 LPWSTR sczId;
17
18 BURN_PAYLOAD* pEntryPayload;
src/burn/engine/container.cpp
+2 -1
@@ -35,7 +35,7 @@ extern "C" HRESULT ContainersParseFromXml(
35
36 pContainers->cContainers = cNodes;
37
38 - // parse search elements
38 + // parse container elements
39 for (DWORD i = 0; i < cNodes; ++i)
40 {
41 BURN_CONTAINER* pContainer = &pContainers->rgContainers[i];
@@ -181,6 +181,7 @@ extern "C" void ContainersUninitialize(
181 ReleaseStr(pContainer->downloadSource.sczUser);
182 ReleaseStr(pContainer->downloadSource.sczPassword);
183 ReleaseStr(pContainer->sczUnverifiedPath);
184 + ReleaseDict(pContainer->sdhPayloads);
185 }
186 MemFree(pContainers->rgContainers);
187 }
src/burn/engine/container.h
+3
@@ -72,6 +72,9 @@ typedef struct _BURN_CONTAINER
72 LPWSTR sczFilePath; // relative path to container.
73 DOWNLOAD_SOURCE downloadSource;
74
75 + DWORD cParsedPayloads;
76 + STRINGDICT_HANDLE sdhPayloads; // value is BURN_PAYLOAD*
77 +
78 BYTE* pbHash;
79 DWORD cbHash;
80 BURN_CONTAINER_VERIFICATION verification;
src/burn/engine/manifest.h
-2
@@ -2,8 +2,6 @@
2 // 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.
3
4
5 -interface IBurnPayload; // forward declare.
6 -
5 #if defined(__cplusplus)
6 extern "C" {
7 #endif
src/burn/engine/payload.cpp
+39 -41
@@ -5,13 +5,6 @@
5
6 // internal function declarations
7
8 -static HRESULT FindEmbeddedBySourcePath(
9 - __in BURN_PAYLOADS* pPayloads,
10 - __in_opt BURN_CONTAINER* pContainer,
11 - __in_z LPCWSTR wzStreamName,
12 - __out BURN_PAYLOAD** ppPayload
13 - );
14 -
8
9 // function definitions
10
@@ -29,6 +22,7 @@ extern "C" HRESULT PayloadsParseFromXml(
22 LPWSTR scz = NULL;
23 BOOL fChainPayload = pContainers && pLayoutPayloads; // These are required when parsing chain payloads.
24 BOOL fValidFileSize = FALSE;
25 + size_t cByteOffset = fChainPayload ? offsetof(BURN_PAYLOAD, sczKey) : offsetof(BURN_PAYLOAD, sczSourcePath);
26
27 // select payload nodes
28 hr = XmlSelectNodes(pixnBundle, L"Payload", &pixnNodes);
@@ -49,7 +43,11 @@ extern "C" HRESULT PayloadsParseFromXml(
43
44 pPayloads->cPayloads = cNodes;
45
52 - // parse search elements
46 + // create dictionary for payloads
47 + hr = DictCreateWithEmbeddedKey(&pPayloads->sdhPayloads, pPayloads->cPayloads, reinterpret_cast<void**>(&pPayloads->rgPayloads), cByteOffset, DICT_FLAG_NONE);
48 + ExitOnFailure(hr, "Failed to create dictionary for payloads.");
49 +
50 + // parse payload elements
51 for (DWORD i = 0; i < cNodes; ++i)
52 {
53 BURN_PAYLOAD* pPayload = &pPayloads->rgPayloads[i];
@@ -104,6 +102,8 @@ extern "C" HRESULT PayloadsParseFromXml(
102 // find container
103 hr = ContainerFindById(pContainers, scz, &pPayload->pContainer);
104 ExitOnFailure(hr, "Failed to to find container: %ls", scz);
105 +
106 + pPayload->pContainer->cParsedPayloads += 1;
107 }
108
109 // @LayoutOnly
@@ -190,12 +190,37 @@ extern "C" HRESULT PayloadsParseFromXml(
190 }
191 }
192
193 + hr = DictAddValue(pPayloads->sdhPayloads, pPayload);
194 + ExitOnFailure(hr, "Failed to add payload to payloads dictionary.");
195 +
196 // prepare next iteration
197 ReleaseNullObject(pixnNode);
198 }
199
200 hr = S_OK;
201
202 + if (pContainers && pContainers->cContainers)
203 + {
204 + for (DWORD i = 0; i < pPayloads->cPayloads; ++i)
205 + {
206 + BURN_PAYLOAD* pPayload = &pPayloads->rgPayloads[i];
207 + BURN_CONTAINER* pContainer = pPayload->pContainer;
208 +
209 + if (!pContainer)
210 + {
211 + continue;
212 + }
213 + else if (!pContainer->sdhPayloads)
214 + {
215 + hr = DictCreateWithEmbeddedKey(&pContainer->sdhPayloads, pContainer->cParsedPayloads, NULL, offsetof(BURN_PAYLOAD, sczSourcePath), DICT_FLAG_NONE);
216 + ExitOnFailure(hr, "Failed to create dictionary for container payloads.");
217 + }
218 +
219 + hr = DictAddValue(pContainer->sdhPayloads, pPayload);
220 + ExitOnFailure(hr, "Failed to add payload to container dictionary.");
221 + }
222 + }
223 +
224 LExit:
225 ReleaseObject(pixnNodes);
226 ReleaseObject(pixnNode);
@@ -237,6 +262,8 @@ extern "C" void PayloadsUninitialize(
262 MemFree(pPayloads->rgPayloads);
263 }
264
265 + ReleaseDict(pPayloads->sdhPayloads);
266 +
267 // clear struct
268 memset(pPayloads, 0, sizeof(BURN_PAYLOADS));
269 }
@@ -265,7 +292,7 @@ extern "C" HRESULT PayloadExtractUXContainer(
292 ExitOnFailure(hr, "Failed to get next stream.");
293
294 // find payload by stream name
268 - hr = PayloadFindEmbeddedBySourcePath(pPayloads, sczStreamName, &pPayload);
295 + hr = PayloadFindEmbeddedBySourcePath(pPayloads->sdhPayloads, sczStreamName, &pPayload);
296 ExitOnFailure(hr, "Failed to find embedded payload: %ls", sczStreamName);
297
298 // make file path
@@ -313,51 +340,22 @@ extern "C" HRESULT PayloadFindById(
340 )
341 {
342 HRESULT hr = S_OK;
316 - BURN_PAYLOAD* pPayload = NULL;
343
318 - for (DWORD i = 0; i < pPayloads->cPayloads; ++i)
319 - {
320 - pPayload = &pPayloads->rgPayloads[i];
321 -
322 - if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPayload->sczKey, -1, wzId, -1))
323 - {
324 - *ppPayload = pPayload;
325 - ExitFunction1(hr = S_OK);
326 - }
327 - }
344 + hr = DictGetValue(pPayloads->sdhPayloads, wzId, reinterpret_cast<void**>(ppPayload));
345
329 - hr = E_NOTFOUND;
330 -
331 -LExit:
346 return hr;
347 }
348
349 extern "C" HRESULT PayloadFindEmbeddedBySourcePath(
336 - __in BURN_PAYLOADS* pPayloads,
350 + __in STRINGDICT_HANDLE sdhPayloads,
351 __in_z LPCWSTR wzStreamName,
352 __out BURN_PAYLOAD** ppPayload
353 )
354 {
355 HRESULT hr = S_OK;
342 - BURN_PAYLOAD* pPayload = NULL;
356
344 - for (DWORD i = 0; i < pPayloads->cPayloads; ++i)
345 - {
346 - pPayload = &pPayloads->rgPayloads[i];
347 -
348 - if (BURN_PAYLOAD_PACKAGING_EMBEDDED == pPayload->packaging)
349 - {
350 - if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPayload->sczSourcePath, -1, wzStreamName, -1))
351 - {
352 - *ppPayload = pPayload;
353 - ExitFunction1(hr = S_OK);
354 - }
355 - }
356 - }
357 + hr = DictGetValue(sdhPayloads, wzStreamName, reinterpret_cast<void**>(ppPayload));
358
358 - hr = E_NOTFOUND;
359 -
360 -LExit:
359 return hr;
360 }
361
src/burn/engine/payload.h
+2 -1
@@ -66,6 +66,7 @@ typedef struct _BURN_PAYLOADS
66 {
67 BURN_PAYLOAD* rgPayloads;
68 DWORD cPayloads;
69 + STRINGDICT_HANDLE sdhPayloads; // value is BURN_PAYLOAD*
70 } BURN_PAYLOADS;
71
72 typedef struct _BURN_PAYLOAD_GROUP_ITEM
@@ -109,7 +110,7 @@ HRESULT PayloadFindById(
110 __out BURN_PAYLOAD** ppPayload
111 );
112 HRESULT PayloadFindEmbeddedBySourcePath(
112 - __in BURN_PAYLOADS* pPayloads,
113 + __in STRINGDICT_HANDLE sdhPayloads,
114 __in_z LPCWSTR wzStreamName,
115 __out BURN_PAYLOAD** ppPayload
116 );
src/burn/engine/userexperience.h
+1 -1
@@ -15,7 +15,7 @@ const DWORD MB_RETRYTRYAGAIN = 0xF;
15
16 // structs
17
18 -typedef struct _BOOTSTRAPPER_ENGINE_CONTEXT BOOTSTRAPPER_ENGINE_CONTEXT;
18 +typedef struct _BOOTSTRAPPER_ENGINE_CONTEXT BOOTSTRAPPER_ENGINE_CONTEXT; // forward declare
19
20 typedef struct _BURN_USER_EXPERIENCE
21 {
src/libs/dutil/WixToolset.DUtil/dictutil.cpp
+58 -70
@@ -72,6 +72,14 @@ struct STRINGDICT_STRUCT
72
73 const int STRINGDICT_HANDLE_BYTES = sizeof(STRINGDICT_STRUCT);
74
75 +static HRESULT CreateDict(
76 + __out_bcount(STRINGDICT_HANDLE_BYTES) STRINGDICT_HANDLE* psdHandle,
77 + __in DICT_TYPE dtType,
78 + __in DWORD dwNumExpectedItems,
79 + __in_opt void** ppvArray,
80 + __in size_t cByteOffset,
81 + __in DICT_FLAG dfFlags
82 + );
83 static HRESULT StringHash(
84 __in const STRINGDICT_STRUCT *psd,
85 __in DWORD dwNumBuckets,
@@ -135,41 +143,7 @@ extern "C" HRESULT DAPI DictCreateWithEmbeddedKey(
143 __in DICT_FLAG dfFlags
144 )
145 {
138 - HRESULT hr = S_OK;
139 -
140 - DictExitOnNull(psdHandle, hr, E_INVALIDARG, "Handle not specified while creating dict");
141 -
142 - // Allocate the handle
143 - *psdHandle = static_cast<STRINGDICT_HANDLE>(MemAlloc(sizeof(STRINGDICT_STRUCT), FALSE));
144 - DictExitOnNull(*psdHandle, hr, E_OUTOFMEMORY, "Failed to allocate dictionary object");
145 -
146 - STRINGDICT_STRUCT *psd = static_cast<STRINGDICT_STRUCT *>(*psdHandle);
147 -
148 - // Fill out the new handle's values
149 - psd->dtType = DICT_EMBEDDED_KEY;
150 - psd->dfFlags = dfFlags;
151 - psd->cByteOffset = cByteOffset;
152 - psd->dwBucketSizeIndex = 0;
153 - psd->dwNumItems = 0;
154 - psd->ppvItemList = NULL;
155 - psd->ppvValueArray = ppvArray;
156 -
157 - // Make psd->dwBucketSizeIndex point to the appropriate spot in the prime
158 - // array based on expected number of items and items to buckets ratio
159 - // Careful: the "-1" in "countof(MAX_BUCKET_SIZES)-1" ensures we don't end
160 - // this loop past the end of the array!
161 - while (psd->dwBucketSizeIndex < (countof(MAX_BUCKET_SIZES)-1) &&
162 - MAX_BUCKET_SIZES[psd->dwBucketSizeIndex] < dwNumExpectedItems * MAX_BUCKETS_TO_ITEMS_RATIO)
163 - {
164 - ++psd->dwBucketSizeIndex;
165 - }
166 -
167 - // Finally, allocate our initial buckets
168 - psd->ppvBuckets = static_cast<void**>(MemAlloc(sizeof(void *) * MAX_BUCKET_SIZES[psd->dwBucketSizeIndex], TRUE));
169 - DictExitOnNull(psd->ppvBuckets, hr, E_OUTOFMEMORY, "Failed to allocate buckets for dictionary");
170 -
171 -LExit:
172 - return hr;
146 + return CreateDict(psdHandle, DICT_EMBEDDED_KEY, dwNumExpectedItems, ppvArray, cByteOffset, dfFlags);
147 }
148
149 // The dict will store a set of keys, with no values associated with them. Use DictAddKey() and DictKeyExists() with this dictionary type.
@@ -179,41 +153,7 @@ extern "C" HRESULT DAPI DictCreateStringList(
153 __in DICT_FLAG dfFlags
154 )
155 {
182 - HRESULT hr = S_OK;
183 -
184 - DictExitOnNull(psdHandle, hr, E_INVALIDARG, "Handle not specified while creating dict");
185 -
186 - // Allocate the handle
187 - *psdHandle = static_cast<STRINGDICT_HANDLE>(MemAlloc(sizeof(STRINGDICT_STRUCT), FALSE));
188 - DictExitOnNull(*psdHandle, hr, E_OUTOFMEMORY, "Failed to allocate dictionary object");
189 -
190 - STRINGDICT_STRUCT *psd = static_cast<STRINGDICT_STRUCT *>(*psdHandle);
191 -
192 - // Fill out the new handle's values
193 - psd->dtType = DICT_STRING_LIST;
194 - psd->dfFlags = dfFlags;
195 - psd->cByteOffset = 0;
196 - psd->dwBucketSizeIndex = 0;
197 - psd->dwNumItems = 0;
198 - psd->ppvItemList = NULL;
199 - psd->ppvValueArray = NULL;
200 -
201 - // Make psd->dwBucketSizeIndex point to the appropriate spot in the prime
202 - // array based on expected number of items and items to buckets ratio
203 - // Careful: the "-1" in "countof(MAX_BUCKET_SIZES)-1" ensures we don't end
204 - // this loop past the end of the array!
205 - while (psd->dwBucketSizeIndex < (countof(MAX_BUCKET_SIZES)-1) &&
206 - MAX_BUCKET_SIZES[psd->dwBucketSizeIndex] < dwNumExpectedItems * MAX_BUCKETS_TO_ITEMS_RATIO)
207 - {
208 - ++psd->dwBucketSizeIndex;
209 - }
210 -
211 - // Finally, allocate our initial buckets
212 - psd->ppvBuckets = static_cast<void**>(MemAlloc(sizeof(void *) * MAX_BUCKET_SIZES[psd->dwBucketSizeIndex], TRUE));
213 - DictExitOnNull(psd->ppvBuckets, hr, E_OUTOFMEMORY, "Failed to allocate buckets for dictionary");
214 -
215 -LExit:
216 - return hr;
156 + return CreateDict(psdHandle, DICT_STRING_LIST, dwNumExpectedItems, NULL, 0, dfFlags);
157 }
158
159 extern "C" HRESULT DAPI DictCreateStringListFromArray(
@@ -467,6 +407,54 @@ extern "C" void DAPI DictDestroy(
407 ReleaseMem(psd);
408 }
409
410 +static HRESULT CreateDict(
411 + __out_bcount(STRINGDICT_HANDLE_BYTES) STRINGDICT_HANDLE* psdHandle,
412 + __in DICT_TYPE dtType,
413 + __in DWORD dwNumExpectedItems,
414 + __in_opt void** ppvArray,
415 + __in size_t cByteOffset,
416 + __in DICT_FLAG dfFlags
417 + )
418 +{
419 + HRESULT hr = S_OK;
420 +
421 + DictExitOnNull(psdHandle, hr, E_INVALIDARG, "Handle not specified while creating dict.");
422 +
423 + // Allocate the handle
424 + *psdHandle = static_cast<STRINGDICT_HANDLE>(MemAlloc(sizeof(STRINGDICT_STRUCT), TRUE));
425 + DictExitOnNull(*psdHandle, hr, E_OUTOFMEMORY, "Failed to allocate dictionary object.");
426 +
427 + STRINGDICT_STRUCT* psd = static_cast<STRINGDICT_STRUCT*>(*psdHandle);
428 +
429 + // Fill out the new handle's values
430 + psd->dtType = dtType;
431 + psd->dfFlags = dfFlags;
432 + psd->cByteOffset = cByteOffset;
433 + psd->ppvValueArray = ppvArray;
434 +
435 + // Make psd->dwBucketSizeIndex point to the appropriate spot in the prime
436 + // array based on expected number of items and items to buckets ratio
437 + // Careful: the "-1" in "countof(MAX_BUCKET_SIZES)-1" ensures we don't end
438 + // this loop past the end of the array!
439 + while (psd->dwBucketSizeIndex < (countof(MAX_BUCKET_SIZES) - 1) &&
440 + MAX_BUCKET_SIZES[psd->dwBucketSizeIndex] < dwNumExpectedItems * MAX_BUCKETS_TO_ITEMS_RATIO)
441 + {
442 + ++psd->dwBucketSizeIndex;
443 + }
444 +
445 + hr = MemAllocArray(reinterpret_cast<LPVOID*>(&psd->ppvBuckets), sizeof(void*), MAX_BUCKET_SIZES[psd->dwBucketSizeIndex]);
446 + DictExitOnFailure(hr, "Failed to allocate buckets for dictionary.");
447 +
448 + if (dwNumExpectedItems)
449 + {
450 + hr = MemAllocArray(reinterpret_cast<LPVOID*>(&psd->ppvItemList), sizeof(void*), dwNumExpectedItems);
451 + DictExitOnFailure(hr, "Failed to pre-allocate item list for dictionary.");
452 + }
453 +
454 +LExit:
455 + return hr;
456 +}
457 +
458 static HRESULT StringHash(
459 __in const STRINGDICT_STRUCT *psd,
460 __in DWORD dwNumBuckets,
src/test/burn/TestData/Manual/BundleB/Bundle.wxs new
+56
@@ -0,0 +1,56 @@
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 +<?ifndef Version?>
4 +<?define Version = 1.0.0.0?>
5 +<?endif?>
6 +
7 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
8 + <!-- The only difference from the template should be the SplashScreen -->
9 + <Bundle Name="~$(var.TestGroupName) - $(var.BundleName)" Version="$(var.Version)" UpgradeCode="$(var.UpgradeCode)" Compressed="yes" SplashScreenSourceFile="..\BafThmutilTesting\theme\star_transparent.bmp">
10 + <Log Prefix="~$(var.TestGroupName)_$(var.BundleName)" />
11 +
12 + <Variable Name="TestGroupName" Value="$(var.TestGroupName)" />
13 +
14 + <?ifdef SoftwareTag?>
15 + <SoftwareTag Regid="regid.1995-08.com.example" InstallPath="[CommonAppDataFolder]regid.1995-08.com.example" />
16 + <?endif?>
17 +
18 + <?ifndef BA?>
19 + <!-- pulled in through the PackageGroupRef below -->
20 + <?elseif $(var.BA) = "TestBAdnc"?>
21 + <!-- pulled in through the PackageGroupRef below -->
22 + <?elseif $(var.BA) = "TestBA_x64"?>
23 + <!-- pulled in through the PackageGroupRef below -->
24 + <?elseif $(var.BA) = "TestBAdnc_x64"?>
25 + <!-- pulled in through the PackageGroupRef below -->
26 + <?elseif $(var.BA) = "WixBA"?>
27 + <!-- pulled in through the PackageGroupRef below -->
28 + <?elseif $(var.BA) = "WixBAdnc_x64"?>
29 + <!-- pulled in through the PackageGroupRef below -->
30 + <?elseif $(var.BA) = "hyperlinkLicense"?>
31 + <BootstrapperApplication>
32 + <bal:WixStandardBootstrapperApplication LicenseUrl="" Theme="hyperlinkLicense" />
33 + </BootstrapperApplication>
34 + <?else?>
35 + <BootstrapperApplicationRef Id="$(var.BA)" />
36 + <?endif?>
37 +
38 + <Chain>
39 + <?ifndef BA?>
40 + <PackageGroupRef Id="TestBA" />
41 + <?elseif $(var.BA) = "TestBAdnc"?>
42 + <PackageGroupRef Id="TestBAdnc" />
43 + <?elseif $(var.BA) = "TestBA_x64"?>
44 + <PackageGroupRef Id="TestBA_x64" />
45 + <?elseif $(var.BA) = "TestBAdnc_x64"?>
46 + <PackageGroupRef Id="TestBAdnc_x64" />
47 + <?elseif $(var.BA) = "WixBA"?>
48 + <PackageGroupRef Id="WixBA" />
49 + <?elseif $(var.BA) = "WixBAdnc_x64"?>
50 + <PackageGroupRef Id="WixBAdnc_x64" />
51 + <?endif?>
52 +
53 + <PackageGroupRef Id="BundlePackages" />
54 + </Chain>
55 + </Bundle>
56 +</Wix>
src/test/burn/TestData/Manual/BundleB/BundleB.wixproj new
+32
@@ -0,0 +1,32 @@
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 +<Project Sdk="WixToolset.Sdk">
3 + <PropertyGroup>
4 + <OutputType>Bundle</OutputType>
5 + <BA>hyperlinkLicense</BA>
6 + <UpgradeCode>{5DE2F206-3C37-4265-81F7-095284E16B08}</UpgradeCode>
7 + <HarvestDirectoryAdditionalOptions>-generate payloadgroup</HarvestDirectoryAdditionalOptions>
8 + </PropertyGroup>
9 + <ItemGroup>
10 + <HarvestDirectory Include="BAPayloads">
11 + <ComponentGroupName>BAPayloads</ComponentGroupName>
12 + <DirectoryRefId>BAPayloads</DirectoryRefId>
13 + <Transforms>ba.xslt</Transforms>
14 + </HarvestDirectory>
15 + <HarvestDirectory Include="PackagePayloads">
16 + <ComponentGroupName>PackagePayloads</ComponentGroupName>
17 + <DirectoryRefId>PackagePayloads</DirectoryRefId>
18 + <Transforms>package.xslt</Transforms>
19 + </HarvestDirectory>
20 + </ItemGroup>
21 + <ItemGroup>
22 + <ProjectReference Include="..\PackageA\PackageA.wixproj" />
23 + </ItemGroup>
24 + <ItemGroup>
25 + <PackageReference Include="WixToolset.Bal.wixext" />
26 + </ItemGroup>
27 + <!-- We do this dynamically to avoid committing so many files to source control. -->
28 + <Target Name="CreateThousandsOfFiles" AfterTargets="BeforeBuild">
29 + <Exec Command='"$(BaseOutputPath)$(Configuration)\netcoreapp3.1\win-x86\testexe.exe" /gf "BAPayloads|10000' WorkingDirectory="$(MSBuildProjectDirectory)" />
30 + <Exec Command='"$(BaseOutputPath)$(Configuration)\netcoreapp3.1\win-x86\testexe.exe" /gf "PackagePayloads|10000' WorkingDirectory="$(MSBuildProjectDirectory)" />
31 + </Target>
32 +</Project>
\ No newline at end of file
src/test/burn/TestData/Manual/BundleB/BundleB.wxs new
+15
@@ -0,0 +1,15 @@
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 +
4 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
5 + <Fragment>
6 + <BootstrapperApplication>
7 + <PayloadGroupRef Id="BAPayloads" />
8 + </BootstrapperApplication>
9 + <PackageGroup Id="BundlePackages">
10 + <MsiPackage Id="PackageA" SourceFile="$(var.PackageA.TargetPath)">
11 + <PayloadGroupRef Id="PackagePayloads" />
12 + </MsiPackage>
13 + </PackageGroup>
14 + </Fragment>
15 +</Wix>
src/test/burn/TestData/Manual/BundleB/ba.xslt new
+21
@@ -0,0 +1,21 @@
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3 + xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
4 + xmlns:wix="http://wixtoolset.org/schemas/v4/wxs"
5 +>
6 + <xsl:output method="xml" indent="yes"/>
7 +
8 + <xsl:template match="@* | node()">
9 + <xsl:copy>
10 + <xsl:apply-templates select="@* | node()"/>
11 + </xsl:copy>
12 + </xsl:template>
13 +
14 + <xsl:template match="wix:Payload" >
15 + <xsl:copy>
16 + <xsl:apply-templates select="@* | node()"/>
17 + <xsl:attribute name="Id">ba_<xsl:value-of select="substring(@SourceFile, 11)" /></xsl:attribute>
18 + <xsl:attribute name="SourceFile">BAPayloads<xsl:value-of select="substring(@SourceFile, 10)" /></xsl:attribute>
19 + </xsl:copy>
20 + </xsl:template>
21 +</xsl:stylesheet>
src/test/burn/TestData/Manual/BundleB/package.xslt new
+21
@@ -0,0 +1,21 @@
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3 + xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
4 + xmlns:wix="http://wixtoolset.org/schemas/v4/wxs"
5 +>
6 + <xsl:output method="xml" indent="yes"/>
7 +
8 + <xsl:template match="@* | node()">
9 + <xsl:copy>
10 + <xsl:apply-templates select="@* | node()"/>
11 + </xsl:copy>
12 + </xsl:template>
13 +
14 + <xsl:template match="wix:Payload" >
15 + <xsl:copy>
16 + <xsl:apply-templates select="@* | node()"/>
17 + <xsl:attribute name="Id">package_<xsl:value-of select="substring(@SourceFile, 11)" /></xsl:attribute>
18 + <xsl:attribute name="SourceFile">PackagePayloads<xsl:value-of select="substring(@SourceFile, 10)" /></xsl:attribute>
19 + </xsl:copy>
20 + </xsl:template>
21 +</xsl:stylesheet>
src/test/burn/TestExe/Task.cs
+22
@@ -59,6 +59,24 @@ namespace TestExe
59 }
60 }
61
62 + public class GenerateFilesTask : Task
63 + {
64 + public GenerateFilesTask(string Data) : base(Data) { }
65 +
66 + public override void RunTask()
67 + {
68 + string[] tokens = this.data.Split(new char[] { '|' }, 2);
69 + string folderPath = System.Environment.ExpandEnvironmentVariables(tokens[0]);
70 + long size = long.Parse(tokens[1]);
71 + Directory.CreateDirectory(folderPath);
72 + var bytes = new byte[0];
73 + for (long i = 1; i <= size; i++)
74 + {
75 + File.WriteAllBytes(Path.Combine(folderPath, $"{i}.txt"), bytes);
76 + }
77 + }
78 + }
79 +
80 public class LargeFileTask : Task
81 {
82 public LargeFileTask(string Data) : base(Data) { }
@@ -163,6 +181,10 @@ namespace TestExe
181 t = new SleepRandomTask(args[i + 1]);
182 tasks.Add(t);
183 break;
184 + case "/gf":
185 + t = new GenerateFilesTask(args[i + 1]);
186 + tasks.Add(t);
187 + break;
188 case "/lf":
189 t = new LargeFileTask(args[i + 1]);
190 tasks.Add(t);
src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
+5 -2
@@ -239,15 +239,18 @@ namespace WixToolset.Core.Burn
239 {
240 foreach (var facade in facades.Values)
241 {
242 - facade.PackageSymbol.Size = 0;
242 + // Use temporary variable to avoid excessive number of PreviousValues.
243 + long packageSize = 0;
244
245 var packagePayloads = packagesPayloads[facade.PackageId];
246
247 foreach (var payload in packagePayloads.Values)
248 {
248 - facade.PackageSymbol.Size += payload.FileSize.Value;
249 + packageSize += payload.FileSize.Value;
250 }
251
252 + facade.PackageSymbol.Size = packageSize;
253 +
254 if (!facade.PackageSymbol.InstallSize.HasValue)
255 {
256 facade.PackageSymbol.InstallSize = facade.PackageSymbol.Size;
src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
+4 -1
@@ -604,12 +604,15 @@ namespace WixToolset.Core.Burn.Bundles
604
605 // Write the BundleExtension elements.
606 var bundleExtensions = this.Section.Symbols.OfType<WixBundleExtensionSymbol>();
607 + var uxPayloadsById = this.UXContainerPayloads.ToDictionary(p => p.Id.Id);
608
609 foreach (var bundleExtension in bundleExtensions)
610 {
611 + var entryPayload = uxPayloadsById[bundleExtension.PayloadRef];
612 +
613 writer.WriteStartElement("BundleExtension");
614 writer.WriteAttributeString("Id", bundleExtension.Id.Id);
612 - writer.WriteAttributeString("EntryPayloadId", bundleExtension.PayloadRef);
615 + writer.WriteAttributeString("EntryPayloadSourcePath", entryPayload.EmbeddedId);
616
617 writer.WriteEndElement();
618 }
src/wix/WixToolset.Core/Compile/CompilerPayload.cs
+2 -2
@@ -143,7 +143,7 @@ namespace WixToolset.Core
143 }
144 }
145
146 - public WixBundlePayloadSymbol CreatePayloadSymbol(ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType previousType = ComplexReferenceChildType.Unknown, string previousId = null)
146 + public WixBundlePayloadSymbol CreatePayloadSymbol(ComplexReferenceParentType parentType, string parentId)
147 {
148 WixBundlePayloadSymbol symbol = null;
149
@@ -179,7 +179,7 @@ namespace WixToolset.Core
179 Version = this.Version,
180 });
181
182 - this.Core.CreateGroupAndOrderingRows(this.SourceLineNumbers, parentType, parentId, ComplexReferenceChildType.Payload, symbol.Id.Id, previousType, previousId);
182 + this.Core.CreateGroupAndOrderingRows(this.SourceLineNumbers, parentType, parentId, ComplexReferenceChildType.Payload, symbol.Id.Id, ComplexReferenceChildType.Unknown, null);
183 }
184
185 return symbol;
src/wix/WixToolset.Core/Compiler_Bundle.cs
+20 -50
@@ -351,7 +351,7 @@ namespace WixToolset.Core
351 this.ParsePayloadGroupElement(child, ComplexReferenceParentType.Layout, Compiler.BundleLayoutOnlyPayloads);
352 break;
353 case "PayloadGroupRef":
354 - this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Layout, Compiler.BundleLayoutOnlyPayloads, ComplexReferenceChildType.Unknown, null);
354 + this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Layout, Compiler.BundleLayoutOnlyPayloads);
355 break;
356 case "RelatedBundle":
357 this.ParseRelatedBundleElement(child);
@@ -649,8 +649,6 @@ namespace WixToolset.Core
649 {
650 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
651 Identifier id = null;
652 - Identifier previousId = null;
653 - var previousType = ComplexReferenceChildType.Unknown;
652
653 foreach (var attrib in node.Attributes())
654 {
@@ -675,16 +673,13 @@ namespace WixToolset.Core
673 switch (child.Name.LocalName)
674 {
675 case "BootstrapperApplicationDll":
678 - previousId = this.ParseBootstrapperApplicationDllElement(child, id, previousType, previousId);
679 - previousType = ComplexReferenceChildType.Payload;
676 + this.ParseBootstrapperApplicationDllElement(child, id);
677 break;
678 case "Payload":
682 - previousId = this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId);
683 - previousType = ComplexReferenceChildType.Payload;
679 + this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId);
680 break;
681 case "PayloadGroupRef":
686 - previousId = this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId);
687 - previousType = ComplexReferenceChildType.PayloadGroup;
682 + this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId);
683 break;
684 default:
685 this.Core.UnexpectedElement(node, child);
@@ -708,9 +703,7 @@ namespace WixToolset.Core
703 /// </summary>
704 /// <param name="node">Element to parse</param>
705 /// <param name="defaultId"></param>
711 - /// <param name="previousType"></param>
712 - /// <param name="previousId"></param>
713 - private Identifier ParseBootstrapperApplicationDllElement(XElement node, Identifier defaultId, ComplexReferenceChildType previousType, Identifier previousId)
706 + private Identifier ParseBootstrapperApplicationDllElement(XElement node, Identifier defaultId)
707 {
708 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
709 var compilerPayload = new CompilerPayload(this.Core, sourceLineNumbers, node)
@@ -805,7 +798,7 @@ namespace WixToolset.Core
798
799 if (!this.Core.EncounteredError)
800 {
808 - compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.Container, Compiler.BurnUXContainerId.Id, previousType, previousId?.Id);
801 + compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.Container, Compiler.BurnUXContainerId.Id);
802 this.Core.AddSymbol(new WixBundleContainerSymbol(sourceLineNumbers, Compiler.BurnUXContainerId)
803 {
804 Name = "bundle-ux.cab",
@@ -829,8 +822,6 @@ namespace WixToolset.Core
822 {
823 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
824 string id = null;
832 - Identifier previousId = null;
833 - var previousType = ComplexReferenceChildType.Unknown;
825
826 foreach (var attrib in node.Attributes())
827 {
@@ -859,12 +850,10 @@ namespace WixToolset.Core
850 switch (child.Name.LocalName)
851 {
852 case "Payload":
862 - previousId = this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId);
863 - previousType = ComplexReferenceChildType.Payload;
853 + this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId);
854 break;
855 case "PayloadGroupRef":
866 - previousId = this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId);
867 - previousType = ComplexReferenceChildType.PayloadGroup;
856 + this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId);
857 break;
858 default:
859 this.Core.UnexpectedElement(node, child);
@@ -1195,8 +1184,6 @@ namespace WixToolset.Core
1184 {
1185 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1186 var compilerPayload = new CompilerPayload(this.Core, sourceLineNumbers, node);
1198 - Identifier previousId = null;
1199 - var previousType = ComplexReferenceChildType.Unknown;
1187
1188 // This list lets us evaluate extension attributes *after* all core attributes
1189 // have been parsed and dealt with, regardless of authoring order.
@@ -1241,9 +1228,7 @@ namespace WixToolset.Core
1228 this.Core.ParseExtensionAttribute(node, extensionAttribute, context);
1229 }
1230
1244 - compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.Container, Compiler.BurnUXContainerId.Id, previousType, previousId?.Id);
1245 - previousId = compilerPayload.Id;
1246 - previousType = ComplexReferenceChildType.Payload;
1231 + compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.Container, Compiler.BurnUXContainerId.Id);
1232
1233 foreach (var child in node.Elements())
1234 {
@@ -1252,12 +1237,10 @@ namespace WixToolset.Core
1237 switch (child.Name.LocalName)
1238 {
1239 case "Payload":
1255 - previousId = this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId);
1256 - previousType = ComplexReferenceChildType.Payload;
1240 + this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId);
1241 break;
1242 case "PayloadGroupRef":
1259 - previousId = this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId);
1260 - previousType = ComplexReferenceChildType.PayloadGroup;
1243 + this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId);
1244 break;
1245 default:
1246 this.Core.UnexpectedElement(node, child);
@@ -1388,12 +1371,9 @@ namespace WixToolset.Core
1371 /// <param name="node">Element to parse</param>
1372 /// <param name="parentType">ComplexReferenceParentType of parent element. (BA or PayloadGroup)</param>
1373 /// <param name="parentId">Identifier of parent element.</param>
1391 - /// <param name="previousType"></param>
1392 - /// <param name="previousId"></param>
1393 - private Identifier ParsePayloadElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId, ComplexReferenceChildType previousType, Identifier previousId)
1374 + private Identifier ParsePayloadElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId)
1375 {
1376 Debug.Assert(ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType);
1396 - Debug.Assert(ComplexReferenceChildType.Unknown == previousType || ComplexReferenceChildType.PayloadGroup == previousType || ComplexReferenceChildType.Payload == previousType);
1377
1378 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1379 var compilerPayload = new CompilerPayload(this.Core, sourceLineNumbers, node);
@@ -1470,7 +1450,7 @@ namespace WixToolset.Core
1450 }
1451 }
1452
1473 - compilerPayload.CreatePayloadSymbol(parentType, parentId?.Id, previousType, previousId?.Id);
1453 + compilerPayload.CreatePayloadSymbol(parentType, parentId?.Id);
1454
1455 return compilerPayload.Id;
1456 }
@@ -1514,8 +1494,6 @@ namespace WixToolset.Core
1494 id = Identifier.Invalid;
1495 }
1496
1517 - var previousType = ComplexReferenceChildType.Unknown;
1518 - Identifier previousId = null;
1497 foreach (var child in node.Elements())
1498 {
1499 if (CompilerCore.WixNamespace == child.Name.Namespace)
@@ -1536,12 +1514,10 @@ namespace WixToolset.Core
1514 packageType = WixBundlePackageType.Msu;
1515 break;
1516 case "Payload":
1539 - previousId = this.ParsePayloadElement(child, ComplexReferenceParentType.PayloadGroup, id, previousType, previousId);
1540 - previousType = ComplexReferenceChildType.Payload;
1517 + this.ParsePayloadElement(child, ComplexReferenceParentType.PayloadGroup, id);
1518 break;
1519 case "PayloadGroupRef":
1543 - previousId = this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.PayloadGroup, id, previousType, previousId);
1544 - previousType = ComplexReferenceChildType.PayloadGroup;
1520 + this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.PayloadGroup, id);
1521 break;
1522 default:
1523 this.Core.UnexpectedElement(node, child);
@@ -1551,12 +1527,9 @@ namespace WixToolset.Core
1527 if (packageType.HasValue)
1528 {
1529 var compilerPayload = this.ParsePackagePayloadElement(null, child, packageType.Value, null);
1554 - var payloadSymbol = compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.PayloadGroup, id?.Id, previousType, previousId?.Id);
1530 + var payloadSymbol = compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.PayloadGroup, id?.Id);
1531 if (payloadSymbol != null)
1532 {
1557 - previousId = payloadSymbol.Id;
1558 - previousType = ComplexReferenceChildType.Payload;
1559 -
1533 this.CreatePackagePayloadSymbol(payloadSymbol.SourceLineNumbers, packageType.Value, payloadSymbol.Id, ComplexReferenceParentType.PayloadGroup, id);
1534 }
1535 }
@@ -1582,12 +1555,9 @@ namespace WixToolset.Core
1555 /// <param name="node">Element to parse.</param>
1556 /// <param name="parentType">ComplexReferenceParentType of parent element (BA or PayloadGroup).</param>
1557 /// <param name="parentId">Identifier of parent element.</param>
1585 - /// <param name="previousType"></param>
1586 - /// <param name="previousId"></param>
1587 - private Identifier ParsePayloadGroupRefElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId, ComplexReferenceChildType previousType, Identifier previousId)
1558 + private Identifier ParsePayloadGroupRefElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId)
1559 {
1560 Debug.Assert(ComplexReferenceParentType.Layout == parentType || ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType);
1590 - Debug.Assert(ComplexReferenceChildType.Unknown == previousType || ComplexReferenceChildType.PayloadGroup == previousType || ComplexReferenceChildType.Payload == previousType);
1561
1562 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1563 Identifier id = null;
@@ -1620,7 +1590,7 @@ namespace WixToolset.Core
1590
1591 this.Core.ParseForExtensionElements(node);
1592
1623 - this.Core.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId?.Id, ComplexReferenceChildType.PayloadGroup, id?.Id, previousType, previousId?.Id);
1593 + this.Core.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId?.Id, ComplexReferenceChildType.PayloadGroup, id?.Id, ComplexReferenceChildType.Unknown, null);
1594
1595 return id;
1596 }
@@ -2259,10 +2229,10 @@ namespace WixToolset.Core
2229 }
2230 break;
2231 case "Payload":
2262 - this.ParsePayloadElement(child, ComplexReferenceParentType.Package, id, ComplexReferenceChildType.Unknown, null);
2232 + this.ParsePayloadElement(child, ComplexReferenceParentType.Package, id);
2233 break;
2234 case "PayloadGroupRef":
2265 - this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Package, id, ComplexReferenceChildType.Unknown, null);
2235 + this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Package, id);
2236 break;
2237 case "Provides":
2238 this.ParseProvidesElement(child, packageType, id.Id, out _);
src/wix/WixToolset.Core/Link/WixGroupingOrdering.cs
+2 -1
@@ -645,13 +645,14 @@ namespace WixToolset.Core.Link
645 this.AddAfter(nestedAfterItems, messageHandler);
646 }
647
648 - // We *don't* propagate ordering information from Packages or
648 + // We *don't* propagate ordering information from Packages, PayloadGroups, or
649 // Containers to their children, because ordering doesn't matter
650 // for them, and a Payload in two Packages (or Containers) can
651 // cause a circular reference to occur.
652 private bool ShouldItemPropagateChildOrdering()
653 {
654 if (String.Equals(nameof(ComplexReferenceParentType.Package), this.Type, StringComparison.Ordinal) ||
655 + String.Equals(nameof(ComplexReferenceParentType.PayloadGroup), this.Type, StringComparison.Ordinal) ||
656 String.Equals(nameof(ComplexReferenceParentType.Container), this.Type, StringComparison.Ordinal))
657 {
658 return false;
src/wix/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs
+3 -7
@@ -211,15 +211,11 @@ namespace WixToolsetTest.CoreIntegration
211
212 var bundleExtensions = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:BundleExtension");
213 Assert.Equal(1, bundleExtensions.Count);
214 - Assert.Equal("<BundleExtension Id='ExampleBext' EntryPayloadId='ExampleBext' />", bundleExtensions[0].GetTestXml());
214 + Assert.Equal("<BundleExtension Id='ExampleBext' EntryPayloadSourcePath='u1' />", bundleExtensions[0].GetTestXml());
215
216 var bundleExtensionPayloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:UX/burn:Payload[@Id='ExampleBext']");
217 Assert.Equal(1, bundleExtensionPayloads.Count);
218 - var ignored = new Dictionary<string, List<string>>
219 - {
220 - { "Payload", new List<string> { "FileSize", "Hash", "SourcePath" } },
221 - };
222 - Assert.Equal("<Payload Id='ExampleBext' FilePath='fakebext.dll' SourcePath='*' />", bundleExtensionPayloads[0].GetTestXml(ignored));
218 + Assert.Equal("<Payload Id='ExampleBext' FilePath='fakebext.dll' SourcePath='u1' />", bundleExtensionPayloads[0].GetTestXml());
219 }
220 }
221
@@ -259,7 +255,7 @@ namespace WixToolsetTest.CoreIntegration
255
256 var bundleExtensions = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:BundleExtension");
257 Assert.Equal(1, bundleExtensions.Count);
262 - Assert.Equal("<BundleExtension Id='ExampleBundleExtension' EntryPayloadId='ExampleBundleExtension' />", bundleExtensions[0].GetTestXml());
258 + Assert.Equal("<BundleExtension Id='ExampleBundleExtension' EntryPayloadSourcePath='u1' />", bundleExtensions[0].GetTestXml());
259
260 var extensionSearches = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:ExtensionSearch");
261 Assert.Equal(2, extensionSearches.Count);