added 1 changeset to branch 'refs/remotes/weinhold-github/pm-flat' old head: 10efbe6c5e9350b8683d5b79ca6b9c75d61131a2 new head: 479ca8169c85621dda097bebe337bcc373eba68f overview: https://github.com/weinhold/Haiku/compare/10efbe6...479ca81 ---------------------------------------------------------------------------- 479ca81: Beginnings of the PackageKit dependency solver Not functional (or tested) yet. The libsolv setup for a somewhat simplified installation case should be more or less complete, though. The solution conversion to to-be-created Haiku data structures and the handling of problems is still missing, though. [ Ingo Weinhold <ingo_weinhold@xxxxxx> ] ---------------------------------------------------------------------------- Commit: 479ca8169c85621dda097bebe337bcc373eba68f Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Mon Apr 1 00:25:37 2013 UTC ---------------------------------------------------------------------------- 10 files changed, 1025 insertions(+) headers/os/package/solver/Solver.h | 43 +++ .../os/package/solver/SolverPackageSpecifier.h | 47 +++ .../package/solver/SolverPackageSpecifierList.h | 46 +++ headers/os/package/solver/SolverRepository.h | 69 ++++ src/kits/package/Jamfile | 2 + src/kits/package/solver/Jamfile | 23 ++ src/kits/package/solver/Solver.cpp | 356 +++++++++++++++++++ .../package/solver/SolverPackageSpecifier.cpp | 79 ++++ .../solver/SolverPackageSpecifierList.cpp | 125 +++++++ src/kits/package/solver/SolverRepository.cpp | 235 ++++++++++++ ---------------------------------------------------------------------------- diff --git a/headers/os/package/solver/Solver.h b/headers/os/package/solver/Solver.h new file mode 100644 index 0000000..d52d739 --- /dev/null +++ b/headers/os/package/solver/Solver.h @@ -0,0 +1,43 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__SOLVER_H_ +#define _PACKAGE__SOLVER_H_ + + +#include <SupportDefs.h> + + +namespace BPackageKit { + + +class BSolverPackageSpecifierList; +class BSolverRepository; + + +class BSolver { +public: + BSolver(); + ~BSolver(); + + status_t Init(); + + status_t AddRepository(BSolverRepository* repository); + + status_t Install( + const BSolverPackageSpecifierList& + packages); + +private: + class Implementation; + +private: + Implementation* fImplementation; +}; + + +} // namespace BPackageKit + + +#endif // _PACKAGE__SOLVER_H_ diff --git a/headers/os/package/solver/SolverPackageSpecifier.h b/headers/os/package/solver/SolverPackageSpecifier.h new file mode 100644 index 0000000..cfef584 --- /dev/null +++ b/headers/os/package/solver/SolverPackageSpecifier.h @@ -0,0 +1,47 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__SOLVER_PACKAGE_SPECIFIER_H_ +#define _PACKAGE__SOLVER_PACKAGE_SPECIFIER_H_ + + +#include <package/PackageResolvableExpression.h> + + +namespace BPackageKit { + + +class BSolverRepository; + + +class BSolverPackageSpecifier { +public: + BSolverPackageSpecifier(); + BSolverPackageSpecifier( + const BPackageResolvableExpression& + expression); + BSolverPackageSpecifier( + BSolverRepository* repository, + const BPackageResolvableExpression& + expression); + BSolverPackageSpecifier( + const BSolverPackageSpecifier& other); + ~BSolverPackageSpecifier(); + + BSolverRepository* Repository() const; + const BPackageResolvableExpression& Expression() const; + + BSolverPackageSpecifier& operator=( + const BSolverPackageSpecifier& other); + +private: + BSolverRepository* fRepository; + BPackageResolvableExpression fExpression; +}; + + +} // namespace BPackageKit + + +#endif // _PACKAGE__SOLVER_PACKAGE_SPECIFIER_H_ diff --git a/headers/os/package/solver/SolverPackageSpecifierList.h b/headers/os/package/solver/SolverPackageSpecifierList.h new file mode 100644 index 0000000..0557dec --- /dev/null +++ b/headers/os/package/solver/SolverPackageSpecifierList.h @@ -0,0 +1,46 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__SOLVER_PACKAGE_SPECIFIER_LIST_H_ +#define _PACKAGE__SOLVER_PACKAGE_SPECIFIER_LIST_H_ + + +#include <SupportDefs.h> + + +namespace BPackageKit { + + +class BSolverPackageSpecifier; + + +class BSolverPackageSpecifierList { +public: + BSolverPackageSpecifierList(); + BSolverPackageSpecifierList( + const BSolverPackageSpecifierList& other); + ~BSolverPackageSpecifierList(); + + bool IsEmpty() const; + int32 CountSpecifiers() const; + const BSolverPackageSpecifier* SpecifierAt(int32 index) const; + + bool AppendSpecifier( + const BSolverPackageSpecifier& specifier); + + BSolverPackageSpecifierList& operator=( + const BSolverPackageSpecifierList& other); + +private: + class Vector; + +private: + Vector* fSpecifiers; +}; + + +} // namespace BPackageKit + + +#endif // _PACKAGE__SOLVER_PACKAGE_SPECIFIER_LIST_H_ diff --git a/headers/os/package/solver/SolverRepository.h b/headers/os/package/solver/SolverRepository.h new file mode 100644 index 0000000..579512d --- /dev/null +++ b/headers/os/package/solver/SolverRepository.h @@ -0,0 +1,69 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__SOLVER_REPOSITORY_H_ +#define _PACKAGE__SOLVER_REPOSITORY_H_ + + +#include <package/PackageDefs.h> +#include <package/PackageInfoSet.h> +#include <String.h> + + +namespace BPackageKit { + + +class BPackageInfo; +class BRepositoryConfig; + + +class BSolverRepository { +public: + enum BAllInstallationLocations { + B_ALL_INSTALLATION_LOCATIONS + }; + + typedef BPackageInfoSet::Iterator Iterator; + +public: + BSolverRepository(); + BSolverRepository(const BString& name); + BSolverRepository( + BPackageInstallationLocation location); + BSolverRepository(BAllInstallationLocations); + BSolverRepository( + const BRepositoryConfig& config); + ~BSolverRepository(); + + status_t SetTo(const BString& name); + status_t SetTo(BPackageInstallationLocation location); + status_t SetTo(BAllInstallationLocations); + status_t SetTo(const BRepositoryConfig& config); + void Unset(); + + status_t InitCheck(); + + bool IsInstalled() const; + + BString Name() const; + uint8 Priority() const; + + status_t AddPackage(const BPackageInfo& info); + status_t AddPackages( + BPackageInstallationLocation location); + + Iterator GetIterator() const; + +private: + BString fName; + uint8 fPriority; + bool fIsInstalled; + BPackageInfoSet fPackages; +}; + + +} // namespace BPackageKit + + +#endif // _PACKAGE__SOLVER_REPOSITORY_H_ diff --git a/src/kits/package/Jamfile b/src/kits/package/Jamfile index a73037b..207e6a1 100644 --- a/src/kits/package/Jamfile +++ b/src/kits/package/Jamfile @@ -74,3 +74,5 @@ SharedLibrary libpackage.so : libshared.a be z $(TARGET_LIBSTDC++) ; + +HaikuSubInclude solver ; diff --git a/src/kits/package/solver/Jamfile b/src/kits/package/solver/Jamfile new file mode 100644 index 0000000..06ea5a5 --- /dev/null +++ b/src/kits/package/solver/Jamfile @@ -0,0 +1,23 @@ +SubDir HAIKU_TOP src kits package solver ; + +UsePrivateHeaders shared ; + +# TODO: Add properly to BuildFeatures and remove here! +HAIKU_LIBSOLV_INSTALL_DIR ?= /Transfer/ports/libsolv-install/boot/common ; +HAIKU_LIBSOLV_HEADERS ?= $(HAIKU_LIBSOLV_INSTALL_DIR)/include ; +HAIKU_LIBSOLV_LIBS ?= $(HAIKU_LIBSOLV_INSTALL_DIR)/lib/libsolv.so + $(HAIKU_LIBSOLV_INSTALL_DIR)/lib/libsolvext.so ; + +SubDirSysHdrs $(HAIKU_LIBSOLV_HEADERS) ; +SubDirHdrs $(HAIKU_LIBSOLV_HEADERS)/solv ; + + +SharedLibrary libpackage_solver.so + : + Solver.cpp + SolverPackageSpecifier.cpp + SolverPackageSpecifierList.cpp + SolverRepository.cpp + : + package $(HAIKU_LIBSOLV_LIBS) be $(TARGET_LIBSTDC++) +; diff --git a/src/kits/package/solver/Solver.cpp b/src/kits/package/solver/Solver.cpp new file mode 100644 index 0000000..10ff02d --- /dev/null +++ b/src/kits/package/solver/Solver.cpp @@ -0,0 +1,356 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold <ingo_weinhold@xxxxxx> + */ + + +#include <package/solver/Solver.h> + +#include <new> + +#include <solv/pool.h> +#include <solv/poolarch.h> +#include <solv/repo.h> +#include <solv/repo_haiku.h> +#include <solv/selection.h> +#include <solv/solver.h> + +#include <package/RepositoryCache.h> +#include <package/solver/SolverPackageSpecifier.h> +#include <package/solver/SolverPackageSpecifierList.h> +#include <package/solver/SolverRepository.h> + +#include <ObjectList.h> + + +// TODO: libsolv doesn't have any helpful out-of-memory handling. It just just +// abort()s. Obviously that isn't good behavior for a library. + + +namespace BPackageKit { + + +// #pragma mark - BSolver::Implementation + + +class BSolver::Implementation { +public: + Implementation(); + ~Implementation(); + + status_t Init(); + + status_t AddRepository(BSolverRepository* repository); + + status_t Install( + const BSolverPackageSpecifierList& + packages); + +private: + struct SolvQueue; + struct RepositoryInfo; + + typedef BObjectList<RepositoryInfo> RepositoryInfoList; + +private: + status_t _AddRepositories(); + RepositoryInfo* _GetRepositoryInfo( + BSolverRepository* repository) const; + +private: + Pool* fPool; + RepositoryInfoList fRepositoryInfos; + RepositoryInfo* fInstalledRepository; +}; + + +struct BSolver::Implementation::SolvQueue : Queue { + SolvQueue() + { + queue_init(this); + } + + ~SolvQueue() + { + queue_free(this); + } +}; + + +struct BSolver::Implementation::RepositoryInfo { + RepositoryInfo(BSolverRepository* repository) + : + fRepository(repository), + fSolvRepo(NULL) + { + } + + BSolverRepository* Repository() const + { + return fRepository; + } + + Repo* SolvRepo() + { + return fSolvRepo; + } + + void SetSolvRepo(Repo* repo) + { + fSolvRepo = repo; + } + +private: + BSolverRepository* fRepository; + Repo* fSolvRepo; +}; + + +// #pragma mark - BSolver + + +BSolver::BSolver() + : + fImplementation(new(std::nothrow) Implementation) +{ +} + + +BSolver::~BSolver() +{ + delete fImplementation; +} + + +status_t +BSolver::Init() +{ + return fImplementation != NULL ? fImplementation->Init() : B_NO_MEMORY; +} + + +status_t +BSolver::AddRepository(BSolverRepository* repository) +{ + return fImplementation != NULL + ? fImplementation->AddRepository(repository) : B_NO_MEMORY; +} + + +status_t +BSolver::Install(const BSolverPackageSpecifierList& packages) +{ + return fImplementation != NULL + ? fImplementation->Install(packages) : B_NO_MEMORY; +} + + +// #pragma mark - BSolver::Implementation + + +BSolver::Implementation::Implementation() + : + fPool(NULL), + fRepositoryInfos(), + fInstalledRepository(NULL) +{ +} + + +BSolver::Implementation::~Implementation() +{ + if (fPool != NULL) + pool_free(fPool); +} + + +status_t +BSolver::Implementation::Init() +{ + // already initialized? + if (fPool != NULL) + return B_BAD_VALUE; + + fPool = pool_create(); + + // Set the system architecture. We use what uname() returns unless we're on + // x86 gcc2. + { + const char* arch; + #ifdef __HAIKU_ARCH_X86 + #if (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_2 + arch = "x86_gcc2"; + #else + arch = "x86"; + #endif + #else + struct utsname info; + if (uname(&info) != 0) + return errno; + arch = info.machine; + #endif + + pool_setarchpolicy(fPool, arch); + } + + return B_OK; +} + + +status_t +BSolver::Implementation::AddRepository(BSolverRepository* repository) +{ + if (repository == NULL || repository->InitCheck() != B_OK) + return B_BAD_VALUE; + + // If the repository represents installed packages, check, if we already + // have such a repository. + if (repository->IsInstalled() && fInstalledRepository != NULL) + return B_BAD_VALUE; + + // add the repository info + RepositoryInfo* info = new(std::nothrow) RepositoryInfo(repository); + if (info == NULL) + return B_NO_MEMORY; + + if (!fRepositoryInfos.AddItem(info)) { + delete info; + return B_NO_MEMORY; + } + + if (repository->IsInstalled()) + fInstalledRepository = info; + + return B_OK; +} + + +status_t +BSolver::Implementation::Install(const BSolverPackageSpecifierList& packages) +{ + if (packages.IsEmpty()) + return B_BAD_VALUE; + +// TODO: Clean up first? + + // add repositories to pool + status_t error = _AddRepositories(); + if (error != B_OK) + return error; + + // prepare pool for solving + pool_createwhatprovides(fPool); + + // add the packages to install to the job queue + SolvQueue jobs; + + int32 packageCount = packages.CountSpecifiers(); + for (int32 i = 0; i < packageCount; i++) { + const BSolverPackageSpecifier& specifier = *packages.SpecifierAt(i); + + // find matching packages + SolvQueue matchingPackages; + + int flags = SELECTION_NAME | SELECTION_PROVIDES | SELECTION_GLOB + | SELECTION_CANON | SELECTION_DOTARCH | SELECTION_REL; +// TODO: All flags needed/useful? + /*int matchFlags =*/ selection_make(fPool, &matchingPackages, + specifier.Expression().Name(), flags); +// TODO: Don't just match the name, but also the version, if given! + if (matchingPackages.count == 0) + return B_NAME_NOT_FOUND; + + // restrict to the matching repository + if (BSolverRepository* repository = specifier.Repository()) { + RepositoryInfo* repositoryInfo = _GetRepositoryInfo(repository); + if (repositoryInfo == NULL) + return B_BAD_VALUE; + + SolvQueue repoFilter; + queue_push2(&repoFilter, + SOLVER_SOLVABLE_REPO/* | SOLVER_SETREPO | SOLVER_SETVENDOR*/, + repositoryInfo->SolvRepo()->repoid); + + selection_filter(fPool, &matchingPackages, &repoFilter); + + if (matchingPackages.count == 0) + return B_NAME_NOT_FOUND; + } + + for (int j = 0; j < matchingPackages.count; j++) + queue_push(&jobs, matchingPackages.elements[j]); + } + + // add solver mode to job queue elements + int solverMode = SOLVER_INSTALL; + for (int i = 0; i < jobs.count; i += 2) { + jobs.elements[i] |= solverMode; +// if (cleandeps) +// jobs.elements[i] |= SOLVER_CLEANDEPS; +// if (forcebest) +// jobs.elements[i] |= SOLVER_FORCEBEST; + } + + // create the solver and solve + Solver* solver = solver_create(fPool); + solver_set_flag(solver, SOLVER_FLAG_SPLITPROVIDES, 1); + solver_set_flag(solver, SOLVER_FLAG_BEST_OBEY_POLICY, 1); + + int problemCount = solver_solve(solver, &jobs); + solver_free(solver); + +// TODO: Problem support! + return problemCount == 0 ? B_OK : B_BAD_VALUE; +} + + +status_t +BSolver::Implementation::_AddRepositories() +{ + if (fInstalledRepository == NULL) + return B_BAD_VALUE; + + int32 repositoryCount = fRepositoryInfos.CountItems(); + for (int32 i = 0; i < repositoryCount; i++) { + RepositoryInfo* repositoryInfo = fRepositoryInfos.ItemAt(i); + BSolverRepository* repository = repositoryInfo->Repository(); + Repo* repo = repo_create(fPool, repository->Name()); + repositoryInfo->SetSolvRepo(repo); + + repo->priority = 256 - repository->Priority(); + repo->appdata = (void*)repositoryInfo; + + BRepositoryCache::Iterator it = repository->GetIterator(); + while (const BPackageInfo* packageInfo = it.Next()) { + repo_add_haiku_package_info(repo, *packageInfo, + REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE); + } + + repo_internalize(repo); + + if (repository->IsInstalled()) + pool_set_installed(fPool, repo); + } + + return B_OK; +} + + +BSolver::Implementation::RepositoryInfo* +BSolver::Implementation::_GetRepositoryInfo(BSolverRepository* repository) const +{ + int32 repositoryCount = fRepositoryInfos.CountItems(); + for (int32 i = 0; i < repositoryCount; i++) { + RepositoryInfo* repositoryInfo = fRepositoryInfos.ItemAt(i); + if (repository == repositoryInfo->Repository()) + return repositoryInfo; + } + + return NULL; +} + + +} // namespace BPackageKit diff --git a/src/kits/package/solver/SolverPackageSpecifier.cpp b/src/kits/package/solver/SolverPackageSpecifier.cpp new file mode 100644 index 0000000..c1469d4 --- /dev/null +++ b/src/kits/package/solver/SolverPackageSpecifier.cpp @@ -0,0 +1,79 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold <ingo_weinhold@xxxxxx> + */ + + +#include <package/solver/SolverPackageSpecifier.h> + + +namespace BPackageKit { + + +BSolverPackageSpecifier::BSolverPackageSpecifier() + : + fRepository(NULL), + fExpression() +{ +} + + +BSolverPackageSpecifier::BSolverPackageSpecifier( + const BPackageResolvableExpression& expression) + : + fRepository(NULL), + fExpression(expression) +{ +} + + +BSolverPackageSpecifier::BSolverPackageSpecifier(BSolverRepository* repository, + const BPackageResolvableExpression& expression) + : + fRepository(repository), + fExpression(expression) +{ +} + + +BSolverPackageSpecifier::BSolverPackageSpecifier( + const BSolverPackageSpecifier& other) + : + fRepository(other.fRepository), + fExpression(other.fExpression) +{ +} + + +BSolverPackageSpecifier::~BSolverPackageSpecifier() +{ +} + + +BSolverRepository* +BSolverPackageSpecifier::Repository() const +{ + return fRepository; +} + + +const BPackageResolvableExpression& +BSolverPackageSpecifier::Expression() const +{ + return fExpression; +} + + +BSolverPackageSpecifier& +BSolverPackageSpecifier::operator=(const BSolverPackageSpecifier& other) +{ + fRepository = other.fRepository; + fExpression = other.fExpression; + return *this; +} + + +} // namespace BPackageKit diff --git a/src/kits/package/solver/SolverPackageSpecifierList.cpp b/src/kits/package/solver/SolverPackageSpecifierList.cpp new file mode 100644 index 0000000..b15c776 --- /dev/null +++ b/src/kits/package/solver/SolverPackageSpecifierList.cpp @@ -0,0 +1,125 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold <ingo_weinhold@xxxxxx> + */ + + +#include <package/solver/SolverPackageSpecifierList.h> + +#include <new> +#include <vector> + +#include <package/solver/SolverPackageSpecifier.h> + + +namespace BPackageKit { + +class BSolverPackageSpecifierList::Vector + : public std::vector<BSolverPackageSpecifier> { +public: + Vector() + : + std::vector<BSolverPackageSpecifier>() + { + } + + Vector(const std::vector<BSolverPackageSpecifier>& other) + : + std::vector<BSolverPackageSpecifier>(other) + { + } +}; + + +BSolverPackageSpecifierList::BSolverPackageSpecifierList() + : + fSpecifiers(NULL) +{ +} + + +BSolverPackageSpecifierList::BSolverPackageSpecifierList( + const BSolverPackageSpecifierList& other) + : + fSpecifiers(NULL) +{ + *this = other; +} + + +BSolverPackageSpecifierList::~BSolverPackageSpecifierList() +{ + delete fSpecifiers; +} + + +bool +BSolverPackageSpecifierList::IsEmpty() const +{ + return fSpecifiers == NULL || fSpecifiers->empty(); +} + + +int32 +BSolverPackageSpecifierList::CountSpecifiers() const +{ + return fSpecifiers != NULL ? fSpecifiers->size() : 0; +} + + +const BSolverPackageSpecifier* +BSolverPackageSpecifierList::SpecifierAt(int32 index) const +{ + if (fSpecifiers == NULL || index < 0 + || (size_t)index >= fSpecifiers->size()) { + return NULL; + } + + return &(*fSpecifiers)[index]; +} + + +bool +BSolverPackageSpecifierList::AppendSpecifier( + const BSolverPackageSpecifier& specifier) +{ + try { + if (fSpecifiers == NULL) { + fSpecifiers = new(std::nothrow) Vector; + if (fSpecifiers == NULL) + return false; + } + + fSpecifiers->push_back(specifier); + return true; + } catch (std::bad_alloc&) { + return false; + } +} + + +BSolverPackageSpecifierList& +BSolverPackageSpecifierList::operator=(const BSolverPackageSpecifierList& other) +{ + if (this == &other) + return *this; + + delete fSpecifiers; + fSpecifiers = NULL; + + if (other.fSpecifiers == NULL) + return *this; + + try { + fSpecifiers = new(std::nothrow) Vector(*other.fSpecifiers); + } catch (std::bad_alloc&) { + } + + return *this; +} + + +} // namespace BPackageKit diff --git a/src/kits/package/solver/SolverRepository.cpp b/src/kits/package/solver/SolverRepository.cpp new file mode 100644 index 0000000..93c2f78 --- /dev/null +++ b/src/kits/package/solver/SolverRepository.cpp @@ -0,0 +1,235 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold <ingo_weinhold@xxxxxx> + */ + + +#include <package/solver/SolverRepository.h> + +#include <package/PackageDefs.h> +#include <package/PackageRoster.h> +#include <package/RepositoryCache.h> +#include <package/RepositoryConfig.h> + + +namespace BPackageKit { + + +BSolverRepository::BSolverRepository() + : + fName(), + fPriority(0), + fIsInstalled(false), + fPackages() +{ +} + + +BSolverRepository::BSolverRepository(const BString& name) + : + fName(), + fPriority(0), + fIsInstalled(false), + fPackages() +{ + SetTo(name); +} + + +BSolverRepository::BSolverRepository(BPackageInstallationLocation location) + : + fName(), + fPriority(0), + fIsInstalled(false), + fPackages() +{ + SetTo(location); +} + + +BSolverRepository::BSolverRepository(BAllInstallationLocations) + : + fName(), + fPriority(0), + fIsInstalled(false), + fPackages() +{ + SetTo(B_ALL_INSTALLATION_LOCATIONS); +} + + +BSolverRepository::BSolverRepository(const BRepositoryConfig& config) + : + fName(), + fPriority(0), + fIsInstalled(false), + fPackages() +{ + SetTo(config); +} + + +BSolverRepository::~BSolverRepository() +{ +} + + +status_t +BSolverRepository::SetTo(const BString& name) +{ + Unset(); + + fName = name; + return fName.IsEmpty() ? B_BAD_VALUE : B_OK; +} + + +status_t +BSolverRepository::SetTo(BPackageInstallationLocation location) +{ + Unset(); + + fName = "Installed"; + + status_t error = AddPackages(location); + if (error != B_OK) { + Unset(); + return error; + } + + fIsInstalled = true; + return B_OK; +} + + +status_t +BSolverRepository::SetTo(BAllInstallationLocations) +{ + status_t error = SetTo(B_PACKAGE_INSTALLATION_LOCATION_SYSTEM); + if (error != B_OK) + return error; + + error = AddPackages(B_PACKAGE_INSTALLATION_LOCATION_COMMON); + if (error != B_OK) { + Unset(); + return error; + } + + error = AddPackages(B_PACKAGE_INSTALLATION_LOCATION_HOME); + if (error != B_OK) { + Unset(); + return error; + } + + return B_OK; +} + + +status_t +BSolverRepository::SetTo(const BRepositoryConfig& config) +{ + Unset(); + + if (config.InitCheck() != B_OK) + return B_BAD_VALUE; + + fName = config.Name(); + fPriority = config.Priority(); + + BPackageRoster roster; + BRepositoryCache cache; + status_t error = roster.GetRepositoryCache(config.Name(), &cache); + if (error != B_OK) { + Unset(); + return error; + } + + BRepositoryCache::Iterator it = cache.GetIterator(); + while (const BPackageInfo* packageInfo = it.Next()) { + error = AddPackage(*packageInfo); + if (error != B_OK) { + Unset(); + return error; + } + } + + return B_OK; +} + + +void +BSolverRepository::Unset() +{ + fName = BString(); + fPriority = 0; + fIsInstalled = false; + fPackages.MakeEmpty(); +} + + +status_t +BSolverRepository::InitCheck() +{ + return fName.IsEmpty() ? B_NO_INIT : B_OK; +} + + +bool +BSolverRepository::IsInstalled() const +{ + return fIsInstalled; +} + + +BString +BSolverRepository::Name() const +{ + return fName; +} + + +uint8 +BSolverRepository::Priority() const +{ + return fPriority; +} + + +status_t +BSolverRepository::AddPackage(const BPackageInfo& info) +{ + return fPackages.AddInfo(info); +} + + +status_t +BSolverRepository::AddPackages(BPackageInstallationLocation location) +{ + BPackageRoster roster; + BPackageInfoSet packageInfos; + status_t error = roster.GetActivePackages(location, packageInfos); + if (error != B_OK) + return error; + + BRepositoryCache::Iterator it = packageInfos.GetIterator(); + while (const BPackageInfo* packageInfo = it.Next()) { + error = fPackages.AddInfo(*packageInfo); + if (error != B_OK) + return error; + } + + return B_OK; +} + + +BSolverRepository::Iterator +BSolverRepository::GetIterator() const +{ + return fPackages.GetIterator(); +} + + +} // namespace BPackageKit