@joebigelow / wix / commits / 66619607

For payloads in a container, prefer the container over local paths. Still consider the destination path to avoid extracting the container for every payload.

For payloads in a container, prefer the container over local paths. Still consider the destination path to avoid extracting the container for every payload. #3640

Sean Hall committed Apr 25, 2021 at 21:44 UTC 666196071cf29d9b489e598a604ae0998c98b6de
3 files changed +43 -11
src/engine/apply.cpp
+36 -9
@@ -1359,8 +1359,8 @@ static HRESULT ApplyAcquireContainerOrPayload(
1359
1360 if (fRetry)
1361 {
1362 - hr = S_OK;
1362 LogErrorId(hr, pContainer ? MSG_APPLY_RETRYING_ACQUIRE_CONTAINER : MSG_APPLY_RETRYING_ACQUIRE_PAYLOAD, pContainer ? pContainer->sczId : pPayloadGroupItem->pPayload->sczKey, NULL, NULL);
1363 + hr = S_OK;
1364 }
1365
1366 ExitOnFailure(hr, "Failed to acquire %hs: %ls", pContainer ? "container" : "payload", pContainer ? pContainer->sczId : pPayloadGroupItem->pPayload->sczKey);
@@ -1389,11 +1389,13 @@ static HRESULT AcquireContainerOrPayload(
1389 LPCWSTR wzDestinationPath = pContainer ? pContainer->sczUnverifiedPath: pPayload->sczUnverifiedPath;
1390 LPCWSTR wzRelativePath = pContainer ? pContainer->sczFilePath : pPayload->sczFilePath;
1391 DWORD dwChosenSearchPath = 0;
1392 + DWORD dwDestinationSearchPath = 0;
1393 BOOTSTRAPPER_CACHE_OPERATION cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_NONE;
1394 BOOTSTRAPPER_CACHE_RESOLVE_OPERATION resolveOperation = BOOTSTRAPPER_CACHE_RESOLVE_NONE;
1395 LPWSTR* pwzDownloadUrl = pContainer ? &pContainer->downloadSource.sczUrl : &pPayload->downloadSource.sczUrl;
1396 LPWSTR* pwzSourcePath = pContainer ? &pContainer->sczSourcePath : &pPayload->sczSourcePath;
1397 BOOL fFoundLocal = FALSE;
1398 + BOOL fPreferExtract = FALSE;
1399
1400 pContext->cSearchPaths = 0;
1401 *pfRetry = FALSE;
@@ -1409,21 +1411,42 @@ static HRESULT AcquireContainerOrPayload(
1411 do
1412 {
1413 fFoundLocal = FALSE;
1414 + fPreferExtract = FALSE;
1415 resolveOperation = BOOTSTRAPPER_CACHE_RESOLVE_NONE;
1416 dwChosenSearchPath = 0;
1417 + dwDestinationSearchPath = 0;
1418
1415 - hr = CacheGetLocalSourcePaths(wzRelativePath, *pwzSourcePath, wzDestinationPath, pContext->wzLayoutDirectory, pContext->pVariables, &pContext->rgSearchPaths, &pContext->cSearchPaths, &dwChosenSearchPath);
1419 + hr = CacheGetLocalSourcePaths(wzRelativePath, *pwzSourcePath, wzDestinationPath, pContext->wzLayoutDirectory, pContext->pVariables, &pContext->rgSearchPaths, &pContext->cSearchPaths, &dwChosenSearchPath, &dwDestinationSearchPath);
1420 ExitOnFailure(hr, "Failed to search local source.");
1421
1418 - for (DWORD i = 0; i < pContext->cSearchPaths; ++i)
1422 + // When a payload comes from a container, the container has the highest chance of being correct.
1423 + // But we want to avoid extracting the container multiple times.
1424 + // So only consider the destination path, which means the container was already extracted.
1425 + if (wzPayloadContainerId)
1426 {
1420 - // If the file exists locally, choose it.
1421 - if (FileExistsEx(pContext->rgSearchPaths[i], NULL))
1427 + if (FileExistsEx(pContext->rgSearchPaths[dwDestinationSearchPath], NULL))
1428 {
1423 - dwChosenSearchPath = i;
1424 -
1429 fFoundLocal = TRUE;
1426 - break;
1430 + dwChosenSearchPath = dwDestinationSearchPath;
1431 + }
1432 + else
1433 + {
1434 + fPreferExtract = TRUE;
1435 + }
1436 + }
1437 +
1438 + if (!fFoundLocal)
1439 + {
1440 + for (DWORD i = 0; i < pContext->cSearchPaths; ++i)
1441 + {
1442 + // If the file exists locally, choose it.
1443 + if (FileExistsEx(pContext->rgSearchPaths[i], NULL))
1444 + {
1445 + dwChosenSearchPath = i;
1446 +
1447 + fFoundLocal = TRUE;
1448 + break;
1449 + }
1450 }
1451 }
1452
@@ -1436,7 +1459,11 @@ static HRESULT AcquireContainerOrPayload(
1459 }
1460 else
1461 {
1439 - if (fFoundLocal) // the file exists locally, so copy it.
1462 + if (fPreferExtract) // the file comes from a container which hasn't been extracted yet, so extract it.
1463 + {
1464 + resolveOperation = BOOTSTRAPPER_CACHE_RESOLVE_CONTAINER;
1465 + }
1466 + else if (fFoundLocal) // the file exists locally, so copy it.
1467 {
1468 resolveOperation = BOOTSTRAPPER_CACHE_RESOLVE_LOCAL;
1469 }
src/engine/cache.cpp
+5 -1
@@ -441,7 +441,8 @@ extern "C" HRESULT CacheGetLocalSourcePaths(
441 __in BURN_VARIABLES* pVariables,
442 __inout LPWSTR** prgSearchPaths,
443 __out DWORD* pcSearchPaths,
444 - __out DWORD* pdwLikelySearchPath
444 + __out DWORD* pdwLikelySearchPath,
445 + __out DWORD* pdwDestinationSearchPath
446 )
447 {
448 HRESULT hr = S_OK;
@@ -454,6 +455,7 @@ extern "C" HRESULT CacheGetLocalSourcePaths(
455 BOOL fSourceIsAbsolute = FALSE;
456 DWORD cSearchPaths = 0;
457 DWORD dwLikelySearchPath = 0;
458 + DWORD dwDestinationSearchPath = 0;
459
460 AssertSz(vfInitializedCache, "Cache wasn't initialized");
461
@@ -486,6 +488,7 @@ extern "C" HRESULT CacheGetLocalSourcePaths(
488 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS);
489 ExitOnFailure(hr, "Failed to ensure size for search paths array.");
490
491 + dwDestinationSearchPath = cSearchPaths;
492 psczPath = *prgSearchPaths + cSearchPaths;
493 ++cSearchPaths;
494
@@ -602,6 +605,7 @@ LExit:
605 AssertSz(cSearchPaths <= BURN_CACHE_MAX_SEARCH_PATHS, "Got more than BURN_CACHE_MAX_SEARCH_PATHS search paths");
606 *pcSearchPaths = cSearchPaths;
607 *pdwLikelySearchPath = dwLikelySearchPath;
608 + *pdwDestinationSearchPath = dwDestinationSearchPath;
609
610 return hr;
611 }
src/engine/cache.h
+2 -1
@@ -102,7 +102,8 @@ HRESULT CacheGetLocalSourcePaths(
102 __in BURN_VARIABLES* pVariables,
103 __inout LPWSTR** prgSearchPaths,
104 __out DWORD* pcSearchPaths,
105 - __out DWORD* pdwLikelySearchPath
105 + __out DWORD* pdwLikelySearchPath,
106 + __out DWORD* pdwDestinationSearchPath
107 );
108 HRESULT CacheSetLastUsedSource(
109 __in BURN_VARIABLES* pVariables,