added 2 changesets to branch 'refs/remotes/HaikuPM-github/package-management' old head: a6c7f5e33c2a4e8596b2901d2fbecdd579d47b36 new head: 5e01af3199254d0f5fd666b32b073a5283230021 overview: https://github.com/haiku/HaikuPM/compare/a6c7f5e...5e01af3 ---------------------------------------------------------------------------- 1047e84: package daemon: Volume::InitPackages(): Fix error case Don't assign fListener, when starting node monitoring fails. 5e01af3: package kit: Add data structures for problem solutions ... and add the problem solutions in LibsolvSolver. [ Ingo Weinhold <ingo_weinhold@xxxxxx> ] ---------------------------------------------------------------------------- 8 files changed, 542 insertions(+), 9 deletions(-) headers/os/package/solver/SolverProblem.h | 12 + .../os/package/solver/SolverProblemSolution.h | 90 +++++++ src/kits/package/Jamfile | 1 + src/kits/package/solver/LibsolvSolver.cpp | 242 ++++++++++++++++++- src/kits/package/solver/LibsolvSolver.h | 13 +- src/kits/package/solver/SolverProblem.cpp | 30 ++- .../package/solver/SolverProblemSolution.cpp | 157 ++++++++++++ src/servers/package/Volume.cpp | 6 +- ############################################################################ Commit: 1047e84f39654c67e966afd0b41d3488d8d9b09d Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Mon Apr 8 18:53:32 2013 UTC package daemon: Volume::InitPackages(): Fix error case Don't assign fListener, when starting node monitoring fails. ---------------------------------------------------------------------------- diff --git a/src/servers/package/Volume.cpp b/src/servers/package/Volume.cpp index b1e1d6a..b366492 100644 --- a/src/servers/package/Volume.cpp +++ b/src/servers/package/Volume.cpp @@ -174,7 +174,9 @@ Volume::InitPackages(Listener* listener) // node-monitor the volume's packages directory status_t error = watch_node(&fPackagesDirectoryRef, B_WATCH_DIRECTORY, BMessenger(this)); - if (error != B_OK) { + if (error == B_OK) { + fListener = listener; + } else { ERROR("Volume::InitPackages(): failed to start watching the packages " "directory of the volume at \"%s\": %s\n", fPath.String(), strerror(error)); @@ -182,8 +184,6 @@ Volume::InitPackages(Listener* listener) // packages directory won't work correctly. } - fListener = listener; - // read the packages directory and get the active packages int fd = OpenRootDirectory(); if (fd < 0) { ############################################################################ Commit: 5e01af3199254d0f5fd666b32b073a5283230021 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Tue Apr 9 15:24:27 2013 UTC package kit: Add data structures for problem solutions ... and add the problem solutions in LibsolvSolver. ---------------------------------------------------------------------------- diff --git a/headers/os/package/solver/SolverProblem.h b/headers/os/package/solver/SolverProblem.h index f660837..4cd6df8 100644 --- a/headers/os/package/solver/SolverProblem.h +++ b/headers/os/package/solver/SolverProblem.h @@ -6,6 +6,7 @@ #define _PACKAGE__SOLVER_PROBLEM_H_ +#include <ObjectList.h> #include <package/PackageResolvableExpression.h> @@ -13,6 +14,7 @@ namespace BPackageKit { class BSolverPackage; +class BSolverProblemSolution; class BSolverProblem { @@ -53,13 +55,23 @@ public: BSolverPackage* TargetPackage() const; const BPackageResolvableExpression& Dependency() const; + int32 CountSolutions() const; + const BSolverProblemSolution* SolutionAt(int32 index) const; + + bool AppendSolution( + BSolverProblemSolution* solution); + BString ToString() const; private: + typedef BObjectList<BSolverProblemSolution> SolutionList; + +private: BType fType; BSolverPackage* fSourcePackage; BSolverPackage* fTargetPackage; BPackageResolvableExpression fDependency; + SolutionList fSolutions; }; diff --git a/headers/os/package/solver/SolverProblemSolution.h b/headers/os/package/solver/SolverProblemSolution.h new file mode 100644 index 0000000..767611d --- /dev/null +++ b/headers/os/package/solver/SolverProblemSolution.h @@ -0,0 +1,90 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__SOLVER_PROBLEM_SOLUTION_H_ +#define _PACKAGE__SOLVER_PROBLEM_SOLUTION_H_ + + +#include <ObjectList.h> +#include <String.h> + + +namespace BPackageKit { + + +class BSolverPackage; + + +class BSolverProblemSolutionElement { +public: + enum BType { + B_UNSPECIFIED, + B_DONT_KEEP, + B_DONT_INSTALL, + B_DONT_INSTALL_MOST_RECENT, + B_DONT_FORBID_INSTALLATION, + B_DONT_DEINSTALL, + B_DONT_DEINSTALL_ALL, + B_DONT_LOCK, + B_KEEP_INFERIOR_ARCHITECTURE, + B_KEEP_EXCLUDED, + B_KEEP_OLD, + B_INSTALL_INFERIOR_ARCHITECTURE, + B_INSTALL_EXCLUDED, + B_INSTALL_OLD, + B_ALLOW_DOWNGRADE, + B_ALLOW_NAME_CHANGE, + B_ALLOW_ARCHITECTURE_CHANGE, + B_ALLOW_VENDOR_CHANGE, + B_ALLOW_REPLACEMENT, + B_ALLOW_DEINSTALLATION + }; + +public: + BSolverProblemSolutionElement(BType type, + BSolverPackage* sourcePackage, + BSolverPackage* targetPackage, + const BString& selection); + ~BSolverProblemSolutionElement(); + + BType Type() const; + BSolverPackage* SourcePackage() const; + BSolverPackage* TargetPackage() const; + const BString& Selection() const; + + BString ToString() const; + +private: + BType fType; + BSolverPackage* fSourcePackage; + BSolverPackage* fTargetPackage; + BString fSelection; +}; + + +class BSolverProblemSolution { +public: + typedef BSolverProblemSolutionElement Element; + +public: + BSolverProblemSolution(); + ~BSolverProblemSolution(); + + int32 CountElements() const; + const Element* ElementAt(int32 index) const; + + bool AppendElement(const Element& element); + +private: + typedef BObjectList<Element> ElementList; + +private: + ElementList fElements; +}; + + +} // namespace BPackageKit + + +#endif // _PACKAGE__SOLVER_PROBLEM_SOLUTION_H_ diff --git a/src/kits/package/Jamfile b/src/kits/package/Jamfile index 6eb0ac4..338acee 100644 --- a/src/kits/package/Jamfile +++ b/src/kits/package/Jamfile @@ -83,6 +83,7 @@ SharedLibrary libpackage.so SolverPackageSpecifier.cpp SolverPackageSpecifierList.cpp SolverProblem.cpp + SolverProblemSolution.cpp SolverRepository.cpp SolverResult.cpp : diff --git a/src/kits/package/solver/LibsolvSolver.cpp b/src/kits/package/solver/LibsolvSolver.cpp index c12e845..7e2a076 100644 --- a/src/kits/package/solver/LibsolvSolver.cpp +++ b/src/kits/package/solver/LibsolvSolver.cpp @@ -13,6 +13,7 @@ #include <new> +#include <solv/policy.h> #include <solv/poolarch.h> #include <solv/repo.h> #include <solv/repo_haiku.h> @@ -85,6 +86,46 @@ private: }; +struct LibsolvSolver::Problem : public BSolverProblem { + Problem(::Id id, BType type, BSolverPackage* sourcePackage, + BSolverPackage* targetPackage, + const BPackageResolvableExpression& dependency) + : + BSolverProblem(type, sourcePackage, targetPackage, dependency), + fId(id) + { + } + + ::Id Id() const + { + return fId; + } + +private: + ::Id fId; +}; + + +struct LibsolvSolver::Solution : public BSolverProblemSolution { + Solution(::Id id, Problem* problem) + : + BSolverProblemSolution(), + fId(id), + fProblem(problem) + { + } + + ::Id Id() const + { + return fId; + } + +private: + ::Id fId; + Problem* fProblem; +}; + + // #pragma mark - LibsolvSolver @@ -546,13 +587,212 @@ LibsolvSolver::_AddProblem(Id problemId) return error; } - BSolverProblem* problem = new(std::nothrow) BSolverProblem(problemType, + Problem* problem = new(std::nothrow) Problem(problemId, problemType, sourcePackage, targetPackage, dependency); if (problem == NULL || !fProblems.AddItem(problem)) { delete problem; return B_NO_MEMORY; } + int solutionCount = solver_solution_count(fSolver, problemId); + for (Id solutionId = 1; solutionId <= solutionCount; solutionId++) { + status_t error = _AddSolution(problem, solutionId); + if (error != B_OK) + return error; + } + + return B_OK; +} + + +status_t +LibsolvSolver::_AddSolution(Problem* problem, Id solutionId) +{ + Solution* solution = new(std::nothrow) Solution(solutionId, problem); + if (solution == NULL || !problem->AppendSolution(solution)) { + delete solution; + return B_NO_MEMORY; + } + + Id elementId = 0; + for (;;) { + Id sourceId; + Id targetId; + elementId = solver_next_solutionelement(fSolver, problem->Id(), + solutionId, elementId, &sourceId, &targetId); + if (elementId == 0) + break; + + status_t error = _AddSolutionElement(solution, sourceId, targetId); + if (error != B_OK) + return error; + } + + return B_OK; +} + + +status_t +LibsolvSolver::_AddSolutionElement(Solution* solution, Id sourceId, Id targetId) +{ + typedef BSolverProblemSolutionElement Element; + + if (sourceId == SOLVER_SOLUTION_JOB + || sourceId == SOLVER_SOLUTION_POOLJOB) { + // targetId is an index into the job queue + if (sourceId == SOLVER_SOLUTION_JOB) + targetId += fSolver->pooljobcnt; + + Id how = fSolver->job.elements[targetId - 1]; + Id what = fSolver->job.elements[targetId]; + Id select = how & SOLVER_SELECTMASK; + + switch (how & SOLVER_JOBMASK) { + case SOLVER_INSTALL: + if (select == SOLVER_SOLVABLE && fInstalledRepository != NULL + && fPool->solvables[what].repo + == fInstalledRepository->SolvRepo()) { + return _AddSolutionElement(solution, Element::B_DONT_KEEP, + fPool->solvables + what, NULL, NULL); + } + + return _AddSolutionElement(solution, + Element::B_DONT_INSTALL, NULL, NULL, + solver_select2str(fPool, select, what)); + + case SOLVER_ERASE: + { + if (select == SOLVER_SOLVABLE + && (fInstalledRepository == NULL + || fPool->solvables[what].repo + != fInstalledRepository->SolvRepo())) { + return _AddSolutionElement(solution, + Element::B_DONT_FORBID_INSTALLATION, + fPool->solvables + what, NULL, NULL); + } + + Element::BType type = select == SOLVER_SOLVABLE_PROVIDES + ? Element::B_DONT_DEINSTALL_ALL : Element::B_DONT_DEINSTALL; + return _AddSolutionElement(solution, type, NULL, NULL, + solver_select2str(fPool, select, what)); + } + + case SOLVER_UPDATE: + return _AddSolutionElement(solution, + Element::B_DONT_INSTALL_MOST_RECENT, NULL, NULL, + solver_select2str(fPool, select, what)); + + case SOLVER_LOCK: + return _AddSolutionElement(solution, Element::B_DONT_LOCK, NULL, + NULL, solver_select2str(fPool, select, what)); + + default: + return _AddSolutionElement(solution, Element::B_UNSPECIFIED, + NULL, NULL, NULL); + } + } + + Solvable* target = targetId != 0 ? fPool->solvables + targetId : NULL; + bool targetInstalled = target && fInstalledRepository + && target->repo == fInstalledRepository->SolvRepo(); + + if (sourceId == SOLVER_SOLUTION_INFARCH) { + return _AddSolutionElement(solution, + targetInstalled + ? Element::B_KEEP_INFERIOR_ARCHITECTURE + : Element::B_INSTALL_INFERIOR_ARCHITECTURE, + target, NULL, NULL); + } + + if (sourceId == SOLVER_SOLUTION_DISTUPGRADE) { + return _AddSolutionElement(solution, + targetInstalled + ? Element::B_KEEP_EXCLUDED : Element::B_INSTALL_EXCLUDED, + target, NULL, NULL); + } + + if (sourceId == SOLVER_SOLUTION_BEST) { + return _AddSolutionElement(solution, + targetInstalled ? Element::B_KEEP_OLD : Element::B_INSTALL_OLD, + target, NULL, NULL); + } + + // replace source with target + Solvable* source = fPool->solvables + sourceId; + if (target == NULL) { + return _AddSolutionElement(solution, Element::B_ALLOW_DEINSTALLATION, + source, NULL, NULL); + } + + int illegalMask = policy_is_illegal(fSolver, source, target, 0); + if ((illegalMask & POLICY_ILLEGAL_DOWNGRADE) != 0) { + status_t error = _AddSolutionElement(solution, + Element::B_ALLOW_DOWNGRADE, source, target, NULL); + if (error != B_OK) + return error; + } + + if ((illegalMask & POLICY_ILLEGAL_NAMECHANGE) != 0) { + status_t error = _AddSolutionElement(solution, + Element::B_ALLOW_NAME_CHANGE, source, target, NULL); + if (error != B_OK) + return error; + } + + if ((illegalMask & POLICY_ILLEGAL_ARCHCHANGE) != 0) { + status_t error = _AddSolutionElement(solution, + Element::B_ALLOW_ARCHITECTURE_CHANGE, source, target, NULL); + if (error != B_OK) + return error; + } + + if ((illegalMask & POLICY_ILLEGAL_VENDORCHANGE) != 0) { + status_t error = _AddSolutionElement(solution, + Element::B_ALLOW_VENDOR_CHANGE, source, target, NULL); + if (error != B_OK) + return error; + } + + if (illegalMask == 0) { + return _AddSolutionElement(solution, Element::B_ALLOW_REPLACEMENT, + source, target, NULL); + } + + return B_OK; +} + + +status_t +LibsolvSolver::_AddSolutionElement(Solution* solution, + BSolverProblemSolutionElement::BType type, Solvable* sourceSolvable, + Solvable* targetSolvable, const char* selectionString) +{ + BSolverPackage* sourcePackage = NULL; + if (sourceSolvable != NULL) { + sourcePackage = _GetPackage(sourceSolvable); + if (sourcePackage == NULL) + return B_ERROR; + } + + BSolverPackage* targetPackage = NULL; + if (targetSolvable != NULL) { + targetPackage = _GetPackage(targetSolvable); + if (targetPackage == NULL) + return B_ERROR; + } + + BString selection; + if (selectionString != NULL && selectionString[0] != '\0') { + selection = selectionString; + if (selection.IsEmpty()) + return B_NO_MEMORY; + } + + if (!solution->AppendElement(BSolverProblemSolutionElement( + type, sourcePackage, targetPackage, selection))) { + return B_NO_MEMORY; + } + return B_OK; } diff --git a/src/kits/package/solver/LibsolvSolver.h b/src/kits/package/solver/LibsolvSolver.h index e31eead..5eb4acb 100644 --- a/src/kits/package/solver/LibsolvSolver.h +++ b/src/kits/package/solver/LibsolvSolver.h @@ -10,6 +10,7 @@ #include <ObjectList.h> #include <package/solver/Solver.h> +#include <package/solver/SolverProblemSolution.h> #include <solv/pool.h> #include <solv/solver.h> @@ -46,9 +47,11 @@ public: private: struct SolvQueue; struct RepositoryInfo; + struct Problem; + struct Solution; typedef BObjectList<RepositoryInfo> RepositoryInfoList; - typedef BObjectList<BSolverProblem> ProblemList; + typedef BObjectList<Problem> ProblemList; typedef std::map<Solvable*, BSolverPackage*> SolvableMap; private: @@ -61,6 +64,14 @@ private: BSolverPackage* _GetPackage(Id solvableId) const; status_t _AddProblem(Id problemId); + status_t _AddSolution(Problem* problem, Id solutionId); + status_t _AddSolutionElement(Solution* solution, + Id sourceId, Id targetId); + status_t _AddSolutionElement(Solution* solution, + BSolverProblemSolutionElement::BType type, + Solvable* sourceSolvable, + Solvable* targetSolvable, + const char* selectionString); status_t _GetResolvableExpression(Id id, BPackageResolvableExpression& _expression) const; diff --git a/src/kits/package/solver/SolverProblem.cpp b/src/kits/package/solver/SolverProblem.cpp index 034f3d2..e0adce0 100644 --- a/src/kits/package/solver/SolverProblem.cpp +++ b/src/kits/package/solver/SolverProblem.cpp @@ -9,9 +9,8 @@ #include <package/solver/SolverProblem.h> -#include <stdio.h> - #include <package/solver/SolverPackage.h> +#include <package/solver/SolverProblemSolution.h> static const char* const kToStringTexts[] = { @@ -45,7 +44,8 @@ BSolverProblem::BSolverProblem(BType type, BSolverPackage* sourcePackage, fType(type), fSourcePackage(sourcePackage), fTargetPackage(targetPackage), - fDependency() + fDependency(), + fSolutions(10, true) { } @@ -57,7 +57,8 @@ BSolverProblem::BSolverProblem(BType type, BSolverPackage* sourcePackage, fType(type), fSourcePackage(sourcePackage), fTargetPackage(targetPackage), - fDependency(dependency) + fDependency(dependency), + fSolutions(10, true) { } @@ -95,6 +96,27 @@ BSolverProblem::Dependency() const } +int32 +BSolverProblem::CountSolutions() const +{ + return fSolutions.CountItems(); +} + + +const BSolverProblemSolution* +BSolverProblem::SolutionAt(int32 index) const +{ + return fSolutions.ItemAt(index); +} + + +bool +BSolverProblem::AppendSolution(BSolverProblemSolution* solution) +{ + return fSolutions.AddItem(solution); +} + + BString BSolverProblem::ToString() const { diff --git a/src/kits/package/solver/SolverProblemSolution.cpp b/src/kits/package/solver/SolverProblemSolution.cpp new file mode 100644 index 0000000..4b6f55f --- /dev/null +++ b/src/kits/package/solver/SolverProblemSolution.cpp @@ -0,0 +1,157 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold <ingo_weinhold@xxxxxx> + */ + + +#include <package/solver/SolverProblemSolution.h> + +#include <package/solver/SolverPackage.h> + + +static const char* const kToStringTexts[] = { + "do something", + "do not keep %source% installed", + "do not install \"%selection%\"", + "do not install the most recent version of \"%selection%\"", + "do not forbid installation of %source%", + "do not deinstall \"%selection%\"", + "do not deinstall all resolvables \"%s\"", + "do not lock \"%selection%\"", + "keep %source% despite its inferior architecture", + "keep %source% from excluded repository", + "keep old %source%", + "install %source% despite its inferior architecture", + "install %source% from excluded repository", + "install %s despite its old version", + "allow downgrade of %source% to %target%", + "allow name change of %source% to %target%", + "allow architecture change of %source% to %target%", + "allow vendor change from \"%sourceVendor%\" (%source%) to " + "\"%targetVendor%\" (%target%)", + "allow replacement of %source% with %target%", + "allow deinstallation of %source%" +}; + + +namespace BPackageKit { + + +// #pragma mark - BSolverProblemSolutionElement + + +BSolverProblemSolutionElement::BSolverProblemSolutionElement(BType type, + BSolverPackage* sourcePackage, BSolverPackage* targetPackage, + const BString& selection) + : + fType(type), + fSourcePackage(sourcePackage), + fTargetPackage(targetPackage), + fSelection(selection) +{ +} + + +BSolverProblemSolutionElement::~BSolverProblemSolutionElement() +{ +} + + +BSolverProblemSolutionElement::BType +BSolverProblemSolutionElement::Type() const +{ + return fType; +} + + +BSolverPackage* +BSolverProblemSolutionElement::SourcePackage() const +{ + return fSourcePackage; +} + + +BSolverPackage* +BSolverProblemSolutionElement::TargetPackage() const +{ + return fTargetPackage; +} + + +const BString& +BSolverProblemSolutionElement::Selection() const +{ + return fSelection; +} + + +BString +BSolverProblemSolutionElement::ToString() const +{ + size_t index = fType; + if (index >= sizeof(kToStringTexts) / sizeof(kToStringTexts[0])) + index = 0; + + return BString(kToStringTexts[index]) + .ReplaceAll("%source%", + fSourcePackage != NULL + ? fSourcePackage->VersionedName().String() : "?") + .ReplaceAll("%target%", + fTargetPackage != NULL + ? fTargetPackage->VersionedName().String() : "?") + .ReplaceAll("%selection%", fSelection) + .ReplaceAll("%sourceVendor%", + fSourcePackage != NULL + ? fSourcePackage->Info().Vendor().String() : "?") + .ReplaceAll("%targetVendor%", + fTargetPackage != NULL + ? fTargetPackage->Info().Vendor().String() : "?"); +} + + +// #pragma mark - BSolverProblemSolution + + +BSolverProblemSolution::BSolverProblemSolution() + : + fElements(10, true) +{ +} + + +BSolverProblemSolution::~BSolverProblemSolution() +{ +} + + +int32 +BSolverProblemSolution::CountElements() const +{ + return fElements.CountItems(); +} + + +const BSolverProblemSolution::Element* +BSolverProblemSolution::ElementAt(int32 index) const +{ + return fElements.ItemAt(index); +} + + +bool +BSolverProblemSolution::AppendElement(const Element& element) +{ + Element* newElement = new(std::nothrow) Element(element); + if (newElement == NULL || !fElements.AddItem(newElement)) { + delete newElement; + return false; + } + + return true; +} + + +} // namespace BPackageKit