diff options
Diffstat (limited to 'src/engine/plan.cpp')
| -rw-r--r-- | src/engine/plan.cpp | 95 |
1 files changed, 49 insertions, 46 deletions
diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp index 65da4ab3..c75c1753 100644 --- a/src/engine/plan.cpp +++ b/src/engine/plan.cpp | |||
| @@ -588,8 +588,8 @@ extern "C" HRESULT PlanRegistration( | |||
| 588 | STRINGDICT_HANDLE sdIgnoreDependents = NULL; | 588 | STRINGDICT_HANDLE sdIgnoreDependents = NULL; |
| 589 | 589 | ||
| 590 | pPlan->fCanAffectMachineState = TRUE; // register the bundle since we're modifying machine state. | 590 | pPlan->fCanAffectMachineState = TRUE; // register the bundle since we're modifying machine state. |
| 591 | |||
| 592 | pPlan->fDisallowRemoval = FALSE; // by default the bundle can be planned to be removed | 591 | pPlan->fDisallowRemoval = FALSE; // by default the bundle can be planned to be removed |
| 592 | pPlan->fIgnoreAllDependents = pRegistration->fIgnoreAllDependents; | ||
| 593 | 593 | ||
| 594 | // Ensure the bundle is cached if not running from the cache. | 594 | // Ensure the bundle is cached if not running from the cache. |
| 595 | if (!CacheBundleRunningFromCache()) | 595 | if (!CacheBundleRunningFromCache()) |
| @@ -633,68 +633,71 @@ extern "C" HRESULT PlanRegistration( | |||
| 633 | ExitOnFailure(hr, "Failed to add self-dependent to ignore dependents."); | 633 | ExitOnFailure(hr, "Failed to add self-dependent to ignore dependents."); |
| 634 | } | 634 | } |
| 635 | 635 | ||
| 636 | // If we are not doing an upgrade, we check to see if there are still dependents on us and if so we skip planning. | 636 | if (!pPlan->fIgnoreAllDependents) |
| 637 | // However, when being upgraded, we always execute our uninstall because a newer version of us is probably | ||
| 638 | // already on the machine and we need to clean up the stuff specific to this bundle. | ||
| 639 | if (BOOTSTRAPPER_RELATION_UPGRADE != relationType) | ||
| 640 | { | 637 | { |
| 641 | // If there were other dependencies to ignore, add them. | 638 | // If we are not doing an upgrade, we check to see if there are still dependents on us and if so we skip planning. |
| 642 | for (DWORD iDependency = 0; iDependency < pRegistration->cIgnoredDependencies; ++iDependency) | 639 | // However, when being upgraded, we always execute our uninstall because a newer version of us is probably |
| 640 | // already on the machine and we need to clean up the stuff specific to this bundle. | ||
| 641 | if (BOOTSTRAPPER_RELATION_UPGRADE != relationType) | ||
| 643 | { | 642 | { |
| 644 | DEPENDENCY* pDependency = pRegistration->rgIgnoredDependencies + iDependency; | 643 | // If there were other dependencies to ignore, add them. |
| 645 | 644 | for (DWORD iDependency = 0; iDependency < pRegistration->cIgnoredDependencies; ++iDependency) | |
| 646 | hr = DictKeyExists(sdIgnoreDependents, pDependency->sczKey); | ||
| 647 | if (E_NOTFOUND != hr) | ||
| 648 | { | ||
| 649 | ExitOnFailure(hr, "Failed to check the dictionary of ignored dependents."); | ||
| 650 | } | ||
| 651 | else | ||
| 652 | { | 645 | { |
| 653 | hr = DictAddKey(sdIgnoreDependents, pDependency->sczKey); | 646 | DEPENDENCY* pDependency = pRegistration->rgIgnoredDependencies + iDependency; |
| 654 | ExitOnFailure(hr, "Failed to add dependent key to ignored dependents."); | ||
| 655 | } | ||
| 656 | } | ||
| 657 | 647 | ||
| 658 | // For addon or patch bundles, dependent related bundles should be ignored. This allows | 648 | hr = DictKeyExists(sdIgnoreDependents, pDependency->sczKey); |
| 659 | // that addon or patch to be removed even though bundles it targets still are registered. | 649 | if (E_NOTFOUND != hr) |
| 660 | for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i) | 650 | { |
| 661 | { | 651 | ExitOnFailure(hr, "Failed to check the dictionary of ignored dependents."); |
| 662 | const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i; | 652 | } |
| 653 | else | ||
| 654 | { | ||
| 655 | hr = DictAddKey(sdIgnoreDependents, pDependency->sczKey); | ||
| 656 | ExitOnFailure(hr, "Failed to add dependent key to ignored dependents."); | ||
| 657 | } | ||
| 658 | } | ||
| 663 | 659 | ||
| 664 | if (BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType) | 660 | // For addon or patch bundles, dependent related bundles should be ignored. This allows |
| 661 | // that addon or patch to be removed even though bundles it targets still are registered. | ||
| 662 | for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i) | ||
| 665 | { | 663 | { |
| 666 | for (DWORD j = 0; j < pRelatedBundle->package.cDependencyProviders; ++j) | 664 | const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + i; |
| 665 | |||
| 666 | if (BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType) | ||
| 667 | { | 667 | { |
| 668 | const BURN_DEPENDENCY_PROVIDER* pProvider = pRelatedBundle->package.rgDependencyProviders + j; | 668 | for (DWORD j = 0; j < pRelatedBundle->package.cDependencyProviders; ++j) |
| 669 | { | ||
| 670 | const BURN_DEPENDENCY_PROVIDER* pProvider = pRelatedBundle->package.rgDependencyProviders + j; | ||
| 669 | 671 | ||
| 670 | hr = DependencyAddIgnoreDependencies(sdIgnoreDependents, pProvider->sczKey); | 672 | hr = DependencyAddIgnoreDependencies(sdIgnoreDependents, pProvider->sczKey); |
| 671 | ExitOnFailure(hr, "Failed to add dependent bundle provider key to ignore dependents."); | 673 | ExitOnFailure(hr, "Failed to add dependent bundle provider key to ignore dependents."); |
| 674 | } | ||
| 672 | } | 675 | } |
| 673 | } | 676 | } |
| 674 | } | ||
| 675 | |||
| 676 | // If there are any (non-ignored and not-planned-to-be-removed) dependents left, skip planning. | ||
| 677 | for (DWORD iDependent = 0; iDependent < pRegistration->cDependents; ++iDependent) | ||
| 678 | { | ||
| 679 | DEPENDENCY* pDependent = pRegistration->rgDependents + iDependent; | ||
| 680 | 677 | ||
| 681 | hr = DictKeyExists(sdIgnoreDependents, pDependent->sczKey); | 678 | // If there are any (non-ignored and not-planned-to-be-removed) dependents left, skip planning. |
| 682 | if (E_NOTFOUND == hr) | 679 | for (DWORD iDependent = 0; iDependent < pRegistration->cDependents; ++iDependent) |
| 683 | { | 680 | { |
| 684 | hr = S_OK; | 681 | DEPENDENCY* pDependent = pRegistration->rgDependents + iDependent; |
| 685 | 682 | ||
| 686 | // TODO: callback to the BA and let it have the option to ignore this dependent? | 683 | hr = DictKeyExists(sdIgnoreDependents, pDependent->sczKey); |
| 687 | if (!pPlan->fDisallowRemoval) | 684 | if (E_NOTFOUND == hr) |
| 688 | { | 685 | { |
| 689 | pPlan->fDisallowRemoval = TRUE; // ensure the registration stays | 686 | hr = S_OK; |
| 690 | *pfContinuePlanning = FALSE; // skip the rest of planning. | ||
| 691 | 687 | ||
| 692 | LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DUE_TO_DEPENDENTS); | 688 | // TODO: callback to the BA and let it have the option to ignore this dependent? |
| 693 | } | 689 | if (!pPlan->fDisallowRemoval) |
| 690 | { | ||
| 691 | pPlan->fDisallowRemoval = TRUE; // ensure the registration stays | ||
| 692 | *pfContinuePlanning = FALSE; // skip the rest of planning. | ||
| 694 | 693 | ||
| 695 | LogId(REPORT_VERBOSE, MSG_DEPENDENCY_BUNDLE_DEPENDENT, pDependent->sczKey, LoggingStringOrUnknownIfNull(pDependent->sczName)); | 694 | LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DUE_TO_DEPENDENTS); |
| 695 | } | ||
| 696 | |||
| 697 | LogId(REPORT_VERBOSE, MSG_DEPENDENCY_BUNDLE_DEPENDENT, pDependent->sczKey, LoggingStringOrUnknownIfNull(pDependent->sczName)); | ||
| 698 | } | ||
| 699 | ExitOnFailure(hr, "Failed to check for remaining dependents during planning."); | ||
| 696 | } | 700 | } |
| 697 | ExitOnFailure(hr, "Failed to check for remaining dependents during planning."); | ||
| 698 | } | 701 | } |
| 699 | } | 702 | } |
| 700 | } | 703 | } |
