From f2cf36df83a6f8e1706fcf7e27734ac44480e5d2 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Mon, 7 Oct 2013 23:05:48 -0400 Subject: [PATCH] HaikuDepot: Resolve system dependencies. - While building the installed package list, resolve the dependencies of the OS packages. Flag the resulting list as protected so as to disallow uninstallation of them in addition to the OS packages. --- src/apps/haiku-depot/MainWindow.cpp | 97 ++++++++++++++++++++++++++--- 1 file changed, 87 insertions(+), 10 deletions(-) diff --git a/src/apps/haiku-depot/MainWindow.cpp b/src/apps/haiku-depot/MainWindow.cpp index 7f2202e762..45d55e16cb 100644 --- a/src/apps/haiku-depot/MainWindow.cpp +++ b/src/apps/haiku-depot/MainWindow.cpp @@ -1,6 +1,7 @@ /* * Copyright 2013, Stephan Aßmus . * Copyright 2013, Rene Gollent, rene@gollent.com. + * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de. * All rights reserved. Distributed under the terms of the MIT License. */ @@ -8,6 +9,8 @@ #include +#include + #include #include #include @@ -23,10 +26,15 @@ #include #include +#include #include #include #include "package/RepositoryCache.h" #include +#include +#include +#include +#include #include "AutoDeleter.h" #include "AutoLocker.h" @@ -50,8 +58,7 @@ enum { using namespace BPackageKit; -using BManager::BPrivate::BException; -using BManager::BPrivate::BFatalErrorException; +using namespace BPackageKit::BManager::BPrivate; typedef std::map PackageInfoMap; @@ -426,9 +433,14 @@ MainWindow::_RefreshPackageList() // installation only, as those must be handled a bit differently // upon uninstallation, since we'd no longer be able to pull them // down remotely. - PackageInfoMap systemPackages; - // any packages flagged as a system package are added to this map. + BStringList systemFlaggedPackages; + // any packages flagged as a system package are added to this list. // such packages cannot be uninstalled, nor can any of their deps. + PackageInfoMap systemInstalledPackages; + // any packages installed in system are added to this list. + // This is later used for dependency resolution of the actual + // system packages in order to compute the list of protected + // dependencies indicated above. for (int32 i = 0; i < packages.CountItems(); i++) { BSolverPackage* package = packages.ItemAt(i); @@ -473,6 +485,10 @@ MainWindow::_RefreshPackageList() manager.SystemRepository())) { modelInfo->AddInstallationLocation( B_PACKAGE_INSTALLATION_LOCATION_SYSTEM); + if (!modelInfo->IsSystemPackage()) { + systemInstalledPackages[repoPackageInfo.FileName()] + = modelInfo; + } } else if (repository == static_cast( manager.HomeRepository())) { modelInfo->AddInstallationLocation( @@ -481,7 +497,7 @@ MainWindow::_RefreshPackageList() } if (modelInfo->IsSystemPackage()) - systemPackages[modelInfo->Title()] = modelInfo; + systemFlaggedPackages.Add(repoPackageInfo.FileName()); } BAutolock lock(fModel.Lock()); @@ -511,11 +527,72 @@ MainWindow::_RefreshPackageList() fModel.AddDepot(it->second); } - for (PackageInfoMap::iterator it = systemPackages.begin(); - it != systemPackages.end(); ++it) { - // TODO: need to resolve deps on all of these and correspondingly - // mark all of those as system packages as well, so we know - // not to show uninstallation as an option. + // compute the OS package dependencies + // create the solver + BSolver* solver; + status_t error = BSolver::Create(solver); + if (error != B_OK) { + printf("failed to create solver: %s\n", strerror(error)); + return; + } + + ObjectDeleter solverDeleter(solver); + BPath systemPath; + error = find_directory(B_SYSTEM_PACKAGES_DIRECTORY, &systemPath); + if (error != B_OK) { + printf("Unable to retrieve system packages directory: %s\n", strerror(error)); + return; + } + + // add the "installed" repository with the given packages + BSolverRepository installedRepository; + { + BRepositoryBuilder installedRepositoryBuilder(installedRepository, + "installed"); + for (int32 i = 0; i < systemFlaggedPackages.CountStrings(); i++) { + BPath packagePath(systemPath); + packagePath.Append(systemFlaggedPackages.StringAt(i)); + installedRepositoryBuilder.AddPackage(packagePath.Path()); + } + installedRepositoryBuilder.AddToSolver(solver, true); + } + + // add system repository + BSolverRepository systemRepository; + { + BRepositoryBuilder systemRepositoryBuilder(systemRepository, + "system"); + for (PackageInfoMap::iterator it = systemInstalledPackages.begin(); + it != systemInstalledPackages.end(); ++it) { + BPath packagePath(systemPath); + packagePath.Append(it->first); + systemRepositoryBuilder.AddPackage(packagePath.Path()); + } + systemRepositoryBuilder.AddToSolver(solver, false); + } + + // solve + error = solver->VerifyInstallation(); + if (error != B_OK) { + printf("failed to compute packages to install: %s\n", strerror(error)); + return; + } + + BSolverResult solverResult; + error = solver->GetResult(solverResult); + if (error != B_OK) { + printf("failed to get packages to install: %s\n", strerror(error)); + return; + } + + for (int32 i = 0; const BSolverResultElement* element + = solverResult.ElementAt(i); i++) { + BSolverPackage* package = element->Package(); + if (element->Type() == BSolverResultElement::B_TYPE_INSTALL) { + PackageInfoMap::iterator it = systemInstalledPackages.find(package->Info().FileName()); + if (it != systemInstalledPackages.end()) + it->second->SetSystemDependency(true); + } } }