void BPackageManager::Uninstall(const BSolverPackageSpecifierList& packages) { Init(B_ADD_INSTALLED_REPOSITORIES); // find the packages that match the specification const BSolverPackageSpecifier* unmatchedSpecifier; PackageList foundPackages; status_t error = fSolver->FindPackages(packages, BSolver::B_FIND_INSTALLED_ONLY, foundPackages, &unmatchedSpecifier); if (error != B_OK) { if (unmatchedSpecifier != NULL) { DIE(error, "failed to find a match for \"%s\"", unmatchedSpecifier->SelectString().String()); } else DIE(error, "failed to compute packages to uninstall"); } // determine the inverse base package closure for the found packages // TODO: Optimize! InstalledRepository& installationRepository = InstallationRepository(); bool foundAnotherPackage; do { foundAnotherPackage = false; int32 count = installationRepository.CountPackages(); for (int32 i = 0; i < count; i++) { BSolverPackage* package = installationRepository.PackageAt(i); if (foundPackages.HasItem(package)) continue; if (_FindBasePackage(foundPackages, package->Info()) >= 0) { foundPackages.AddItem(package); foundAnotherPackage = true; } } } while (foundAnotherPackage); // remove the packages from the repository for (int32 i = 0; BSolverPackage* package = foundPackages.ItemAt(i); i++) installationRepository.DisablePackage(package); for (;;) { error = fSolver->VerifyInstallation(BSolver::B_VERIFY_ALLOW_UNINSTALL); if (error != B_OK) DIE(error, "failed to compute packages to uninstall"); _HandleProblems(); // (virtually) apply the result to this repository _AnalyzeResult(); for (int32 i = foundPackages.CountItems() - 1; i >= 0; i--) { if (!installationRepository.PackagesToDeactivate() .AddItem(foundPackages.ItemAt(i))) { throw std::bad_alloc(); } } installationRepository.ApplyChanges(); // verify the next specific respository if (!_NextSpecificInstallationLocation()) break; foundPackages.MakeEmpty(); // NOTE: In theory, after verifying a more specific location, it would // be more correct to compute the inverse base package closure for the // packages we need to uninstall and (if anything changed) verify again. // In practice, however, base packages are always required with an exact // version (ATM). If that base package still exist in a more general // location (the only reason why the package requiring the base package // wouldn't be marked to be uninstalled as well) there shouldn't have // been any reason to remove it from the more specific location in the // first place. } _ConfirmChanges(true); _ApplyPackageChanges(true); }