[haiku-commits] BRANCH HaikuPM-github.package-management - in src: kits/package/solver bin/pkgman

  • From: HaikuPM-github.package-management <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 21 Apr 2013 03:00:35 +0200 (CEST)

added 4 changesets to branch 'refs/remotes/HaikuPM-github/package-management'
old head: 7c092d4d865eb53029c28fb5b1ddfbbada85899f
new head: 2f028e9a2dc4b33ecac66d8fd491244a02d0f677
overview: https://github.com/haiku/HaikuPM/compare/7c092d4...2f028e9

----------------------------------------------------------------------------

adc49c4: pkgman install: better out-of-memory error messages

ec41ff5: pkgman install: Refresh repositories first

8e6c363: BSolver/LibsolvSolver: Add problem solution selection support
  
  ... and re-solving.

2f028e9: pkgman install: Add problem solution selection support

                                    [ Ingo Weinhold <ingo_weinhold@xxxxxx> ]

----------------------------------------------------------------------------

4 files changed, 220 insertions(+), 48 deletions(-)
headers/os/package/solver/Solver.h        |   6 ++
src/bin/pkgman/command_install.cpp        | 115 ++++++++++++++++-----
src/kits/package/solver/LibsolvSolver.cpp | 137 +++++++++++++++++++++-----
src/kits/package/solver/LibsolvSolver.h   |  10 +-

############################################################################

Commit:      adc49c411a101e1372d77d95c3473cdbd5dace06
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Apr 20 19:47:35 2013 UTC

pkgman install: better out-of-memory error messages

----------------------------------------------------------------------------

diff --git a/src/bin/pkgman/command_install.cpp 
b/src/bin/pkgman/command_install.cpp
index 743f19e..0e1c3e0 100644
--- a/src/bin/pkgman/command_install.cpp
+++ b/src/bin/pkgman/command_install.cpp
@@ -178,7 +178,7 @@ InstallCommand::Execute(int argc, const char* const* argv)
        for (int32 i = 0; i < repositoryNameCount; i++) {
                Repository* repository = new(std::nothrow) Repository;
                if (repository == NULL || 
!otherRepositories.AddItem(repository))
-                       DIE(B_NO_MEMORY, "out of memory");
+                       DIE(B_NO_MEMORY, "failed to create/add repository 
object");
 
                const BString& name = repositoryNames.StringAt(i);
                error = repository->Init(roster, name);
@@ -306,7 +306,7 @@ exit(1);
                                BString url = repository->Config().BaseURL();
                                BString 
fileName(package->Info().CanonicalFileName());
                                if (fileName.IsEmpty())
-                                       DIE(B_NO_MEMORY, "out of memory");
+                                       DIE(B_NO_MEMORY, "failed to allocate 
file name");
                                url << '/' << fileName;
 
                                BEntry entry;

############################################################################

Commit:      ec41ff587ff27f05dd852cd58a91bcb70043be41
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Apr 20 22:36:31 2013 UTC

pkgman install: Refresh repositories first

----------------------------------------------------------------------------

diff --git a/src/bin/pkgman/command_install.cpp 
b/src/bin/pkgman/command_install.cpp
index 0e1c3e0..b89dd0e 100644
--- a/src/bin/pkgman/command_install.cpp
+++ b/src/bin/pkgman/command_install.cpp
@@ -15,6 +15,7 @@
 #include <Directory.h>
 #include <package/DownloadFileRequest.h>
 #include <package/PackageRoster.h>
+#include <package/RefreshRepositoryRequest.h>
 #include <package/RepositoryConfig.h>
 #include <package/solver/SolverPackageSpecifier.h>
 #include <package/solver/SolverPackageSpecifierList.h>
@@ -65,8 +66,22 @@ struct Repository : public BSolverRepository {
        {
        }
 
-       status_t Init(BPackageRoster& roster, const char* name)
+       status_t Init(BPackageRoster& roster, BContext& context, const char* 
name)
        {
+               // get the repository config
+               status_t error = roster.GetRepositoryConfig(name, &fConfig);
+               if (error != B_OK)
+                       return error;
+
+               // refresh
+               BRefreshRepositoryRequest refreshRequest(context, fConfig);
+               error = refreshRequest.Process();
+               if (error != B_OK) {
+                       WARN(error, "refreshing repository \"%s\" failed", 
name);
+                       return B_OK;
+               }
+
+               // re-get the config
                return roster.GetRepositoryConfig(name, &fConfig);
        }
 
@@ -119,8 +134,6 @@ InstallCommand::Execute(int argc, const char* const* argv)
        int packageCount = argc - optind;
        const char* const* packages = argv + optind;
 
-// TODO: Refresh repositories.
-
        // create the solver
        BSolver* solver;
        status_t error = BSolver::Create(solver);
@@ -167,6 +180,10 @@ InstallCommand::Execute(int argc, const char* const* argv)
        }
 
        // other repositories
+       DecisionProvider decisionProvider;
+       JobStateListener listener;
+       BContext context(decisionProvider, listener);
+
        BObjectList<Repository> otherRepositories(10, true);
        BPackageRoster roster;
        BStringList repositoryNames;
@@ -181,7 +198,7 @@ InstallCommand::Execute(int argc, const char* const* argv)
                        DIE(B_NO_MEMORY, "failed to create/add repository 
object");
 
                const BString& name = repositoryNames.StringAt(i);
-               error = repository->Init(roster, name);
+               error = repository->Init(roster, context, name);
                if (error != B_OK) {
                        WARN(error, "failed to get config for repository 
\"%s\". Skipping.",
                                name.String());
@@ -268,7 +285,6 @@ exit(1);
 // other information) should, however, be provided by the repository cache in
 // some way. Extend BPackageInfo? Create a BPackageFileInfo?
 
-       DecisionProvider decisionProvider;
        if (!decisionProvider.YesNoDecisionNeeded(BString(), "Continue?", "y", 
"n",
                        "y")) {
                return 1;
@@ -287,9 +303,6 @@ exit(1);
                DIE(error, "failed to create transaction");
 
        // download the new packages and prepare the transaction
-       JobStateListener listener;
-       BContext context(decisionProvider, listener);
-
        for (int32 i = 0; const BSolverResultElement* element = 
result.ElementAt(i);
                        i++) {
                BSolverPackage* package = element->Package();

############################################################################

Commit:      8e6c3631a3e6deca3ca008bbce20bf30ec616d63
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sun Apr 21 00:46:26 2013 UTC

BSolver/LibsolvSolver: Add problem solution selection support

... and re-solving.

----------------------------------------------------------------------------

diff --git a/headers/os/package/solver/Solver.h 
b/headers/os/package/solver/Solver.h
index 90c0045..f72afff 100644
--- a/headers/os/package/solver/Solver.h
+++ b/headers/os/package/solver/Solver.h
@@ -17,6 +17,7 @@ class BSolverPackage;
 class BSolverPackageSpecifier;
 class BSolverPackageSpecifierList;
 class BSolverProblem;
+class BSolverProblemSolution;
 class BSolverRepository;
 class BSolverResult;
 
@@ -58,6 +59,11 @@ public:
        virtual int32                           CountProblems() const = 0;
        virtual BSolverProblem*         ProblemAt(int32 index) const = 0;
 
+       virtual status_t                        SelectProblemSolution(
+                                                                       
BSolverProblem* problem,
+                                                                       const 
BSolverProblemSolution* solution) = 0;
+       virtual status_t                        SolveAgain() = 0;
+
        virtual status_t                        GetResult(BSolverResult& 
_result) = 0;
 
 protected:
diff --git a/src/kits/package/solver/LibsolvSolver.cpp 
b/src/kits/package/solver/LibsolvSolver.cpp
index 460befd..2f02a27 100644
--- a/src/kits/package/solver/LibsolvSolver.cpp
+++ b/src/kits/package/solver/LibsolvSolver.cpp
@@ -118,7 +118,8 @@ struct LibsolvSolver::Problem : public BSolverProblem {
                const BPackageResolvableExpression& dependency)
                :
                BSolverProblem(type, sourcePackage, targetPackage, dependency),
-               fId(id)
+               fId(id),
+               fSelectedSolution(NULL)
        {
        }
 
@@ -127,13 +128,24 @@ struct LibsolvSolver::Problem : public BSolverProblem {
                return fId;
        }
 
+       const Solution* SelectedSolution() const
+       {
+               return fSelectedSolution;
+       }
+
+       void SetSelectedSolution(const Solution* solution)
+       {
+               fSelectedSolution = solution;
+       }
+
 private:
-       ::Id    fId;
+       ::Id                    fId;
+       const Solution* fSelectedSolution;
 };
 
 
 struct LibsolvSolver::Solution : public BSolverProblemSolution {
-       Solution(::Id id, Problem* problem)
+       Solution(::Id id, LibsolvSolver::Problem* problem)
                :
                BSolverProblemSolution(),
                fId(id),
@@ -146,9 +158,14 @@ struct LibsolvSolver::Solution : public 
BSolverProblemSolution {
                return fId;
        }
 
+       LibsolvSolver::Problem* Problem() const
+       {
+               return fProblem;
+       }
+
 private:
-       ::Id            fId;
-       Problem*        fProblem;
+       ::Id                                    fId;
+       LibsolvSolver::Problem* fProblem;
 };
 
 
@@ -159,6 +176,7 @@ LibsolvSolver::LibsolvSolver()
        :
        fPool(NULL),
        fSolver(NULL),
+       fJobs(NULL),
        fRepositoryInfos(10, true),
        fInstalledRepository(NULL),
        fSolvablePackages(),
@@ -299,7 +317,9 @@ LibsolvSolver::Install(const BSolverPackageSpecifierList& 
packages,
                return error;
 
        // add the packages to install to the job queue
-       SolvQueue jobs;
+       error = _InitJobQueue();
+       if (error != B_OK)
+               return error;
 
        int32 packageCount = packages.CountSpecifiers();
        for (int32 i = 0; i < packageCount; i++) {
@@ -317,7 +337,7 @@ LibsolvSolver::Install(const BSolverPackageSpecifierList& 
packages,
                                        return B_BAD_VALUE;
                                }
 
-                               queue_push2(&jobs, SOLVER_SOLVABLE,
+                               queue_push2(fJobs, SOLVER_SOLVABLE,
                                        solvable - fPool->solvables);
                                break;
                        }
@@ -359,15 +379,15 @@ LibsolvSolver::Install(const BSolverPackageSpecifierList& 
packages,
 #endif
 
                                for (int j = 0; j < matchingPackages.count; j++)
-                                       queue_push(&jobs, 
matchingPackages.elements[j]);
+                                       queue_push(fJobs, 
matchingPackages.elements[j]);
                        }
                }
        }
 
        // set jobs' solver mode and solve
-       _SetJobsSolverMode(jobs, SOLVER_INSTALL);
+       _SetJobsSolverMode(*fJobs, SOLVER_INSTALL);
 
-       return _Solve(jobs);
+       return _Solve(false);
 }
 
 
@@ -383,13 +403,56 @@ LibsolvSolver::VerifyInstallation()
                return error;
 
        // add the verify job to the job queue
-       SolvQueue jobs;
-       queue_push2(&jobs, SOLVER_SOLVABLE_ALL, 0);
+       error = _InitJobQueue();
+       if (error != B_OK)
+               return error;
+
+       queue_push2(fJobs, SOLVER_SOLVABLE_ALL, 0);
 
        // set jobs' solver mode and solve
-       _SetJobsSolverMode(jobs, SOLVER_VERIFY);
+       _SetJobsSolverMode(*fJobs, SOLVER_VERIFY);
+
+       return _Solve(false);
+}
+
+
+status_t
+LibsolvSolver::SelectProblemSolution(BSolverProblem* _problem,
+       const BSolverProblemSolution* _solution)
+{
+       if (_problem == NULL)
+               return B_BAD_VALUE;
+
+       Problem* problem = static_cast<Problem*>(_problem);
+       if (_solution == NULL) {
+               problem->SetSelectedSolution(NULL);
+               return B_OK;
+       }
 
-       return _Solve(jobs);
+       const Solution* solution = static_cast<const Solution*>(_solution);
+       if (solution->Problem() != problem)
+               return B_BAD_VALUE;
+
+       problem->SetSelectedSolution(solution);
+       return B_OK;
+}
+
+
+status_t
+LibsolvSolver::SolveAgain()
+{
+       if (fSolver == NULL || fJobs == NULL)
+               return B_BAD_VALUE;
+
+       // iterate through all problems and propagate the selected solutions
+       int32 problemCount = fProblems.CountItems();
+       for (int32 i = 0; i < problemCount; i++) {
+               Problem* problem = fProblems.ItemAt(i);
+               if (const Solution* solution = problem->SelectedSolution())
+                       solver_take_solution(fSolver, problem->Id(), 
solution->Id(), fJobs);
+       }
+
+       return _Solve(true);
 }
 
 
@@ -518,6 +581,16 @@ LibsolvSolver::_InitPool()
 }
 
 
+status_t
+LibsolvSolver::_InitJobQueue()
+{
+       _CleanupJobQueue();
+
+       fJobs = new(std::nothrow) SolvQueue;
+       return fJobs != NULL ? B_OK : B_NO_MEMORY;;
+}
+
+
 void
 LibsolvSolver::_Cleanup()
 {
@@ -532,8 +605,8 @@ LibsolvSolver::_Cleanup()
 void
 LibsolvSolver::_CleanupPool()
 {
-       // clean up solver data
-       _CleanupSolver();
+       // clean up jobs and solver data
+       _CleanupJobQueue();
 
        // clean up our data structures that depend on/refer to libsolv pool 
data
        fSolvablePackages.clear();
@@ -552,6 +625,16 @@ LibsolvSolver::_CleanupPool()
 
 
 void
+LibsolvSolver::_CleanupJobQueue()
+{
+       _CleanupSolver();
+
+       delete fJobs;
+       fJobs = NULL;
+}
+
+
+void
 LibsolvSolver::_CleanupSolver()
 {
        fProblems.MakeEmpty();
@@ -1055,16 +1138,24 @@ LibsolvSolver::_GetResolvableExpression(Id id,
 
 
 status_t
-LibsolvSolver::_Solve(Queue& jobs)
+LibsolvSolver::_Solve(bool solveAgain)
 {
-       _CleanupSolver();
+       if (fJobs == NULL)
+               return B_BAD_VALUE;
+
+       if (solveAgain) {
+               if (fSolver == NULL)
+                       return B_BAD_VALUE;
+       } else {
+               _CleanupSolver();
 
-       // create the solver and solve
-       fSolver = solver_create(fPool);
-       solver_set_flag(fSolver, SOLVER_FLAG_SPLITPROVIDES, 1);
-       solver_set_flag(fSolver, SOLVER_FLAG_BEST_OBEY_POLICY, 1);
+               // create the solver and solve
+               fSolver = solver_create(fPool);
+               solver_set_flag(fSolver, SOLVER_FLAG_SPLITPROVIDES, 1);
+               solver_set_flag(fSolver, SOLVER_FLAG_BEST_OBEY_POLICY, 1);
+       }
 
-       int problemCount = solver_solve(fSolver, &jobs);
+       int problemCount = solver_solve(fSolver, fJobs);
 
        // get the problems (if any)
        fProblems.MakeEmpty();
diff --git a/src/kits/package/solver/LibsolvSolver.h 
b/src/kits/package/solver/LibsolvSolver.h
index 09c6dba..a4dcdd7 100644
--- a/src/kits/package/solver/LibsolvSolver.h
+++ b/src/kits/package/solver/LibsolvSolver.h
@@ -48,6 +48,11 @@ public:
        virtual int32                           CountProblems() const;
        virtual BSolverProblem*         ProblemAt(int32 index) const;
 
+       virtual status_t                        SelectProblemSolution(
+                                                                       
BSolverProblem* problem,
+                                                                       const 
BSolverProblemSolution* solution);
+       virtual status_t                        SolveAgain();
+
        virtual status_t                        GetResult(BSolverResult& 
_result);
 
 private:
@@ -64,8 +69,10 @@ private:
 
 private:
                        status_t                        _InitPool();
+                       status_t                        _InitJobQueue();
                        void                            _Cleanup();
                        void                            _CleanupPool();
+                       void                            _CleanupJobQueue();
                        void                            _CleanupSolver();
 
                        bool                            
_HaveRepositoriesChanged() const;
@@ -89,12 +96,13 @@ private:
                                                                        
BPackageResolvableExpression& _expression)
                                                                        const;
 
-                       status_t                        _Solve(Queue& jobs);
+                       status_t                        _Solve(bool solveAgain);
                        void                            
_SetJobsSolverMode(Queue& jobs, int solverMode);
 
 private:
                        Pool*                           fPool;
                        Solver*                         fSolver;
+                       SolvQueue*                      fJobs;
                        RepositoryInfoList      fRepositoryInfos;
                        RepositoryInfo*         fInstalledRepository;
                        SolvableMap                     fSolvablePackages;

############################################################################

Commit:      2f028e9a2dc4b33ecac66d8fd491244a02d0f677
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sun Apr 21 00:47:51 2013 UTC

pkgman install: Add problem solution selection support

----------------------------------------------------------------------------

diff --git a/src/bin/pkgman/command_install.cpp 
b/src/bin/pkgman/command_install.cpp
index b89dd0e..0554cea 100644
--- a/src/bin/pkgman/command_install.cpp
+++ b/src/bin/pkgman/command_install.cpp
@@ -233,24 +233,60 @@ InstallCommand::Execute(int argc, const char* const* argv)
 
                int32 problemCount = solver->CountProblems();
                for (int32 i = 0; i < problemCount; i++) {
+                       // print problem and possible solutions
                        BSolverProblem* problem = solver->ProblemAt(i);
-                       printf("  %" B_PRId32 ": %s\n", i + 1,
+                       printf("problem %" B_PRId32 ": %s\n", i + 1,
                                problem->ToString().String());
 
                        int32 solutionCount = problem->CountSolutions();
                        for (int32 k = 0; k < solutionCount; k++) {
                                const BSolverProblemSolution* solution = 
problem->SolutionAt(k);
-                               printf("    solution %" B_PRId32 ":\n", k + 1);
+                               printf("  solution %" B_PRId32 ":\n", k + 1);
                                int32 elementCount = solution->CountElements();
                                for (int32 l = 0; l < elementCount; l++) {
                                        const BSolverProblemSolutionElement* 
element
                                                = solution->ElementAt(l);
-                                       printf("      - %s\n", 
element->ToString().String());
+                                       printf("    - %s\n", 
element->ToString().String());
                                }
                        }
+
+                       // let the user choose a solution
+                       printf("Please select a solution, skip the problem for 
now or "
+                               "quit.\n");
+                       for (;;) {
+                               if (solutionCount > 1)
+                                       printf("select [1...%" B_PRId32 "/s/q]: 
", solutionCount);
+                               else
+                                       printf("select [1/s/q]: ");
+       
+                               char buffer[32];
+                               if (fgets(buffer, sizeof(buffer), stdin) == NULL
+                                       || strcmp(buffer, "q\n") == 0) {
+                                       exit(1);
+                               }
+
+                               if (strcmp(buffer, "s\n") == 0)
+                                       break;
+
+                               char* end;
+                               long selected = strtol(buffer, &end, 0);
+                               if (end == buffer || *end != '\n' || selected < 
1
+                                       || selected > solutionCount) {
+                                       printf("*** invalid input\n");
+                                       continue;
+                               }
+
+                               error = solver->SelectProblemSolution(problem,
+                                       problem->SolutionAt(selected - 1));
+                               if (error != B_OK)
+                                       DIE(error, "failed to set solution");
+                               break;
+                       }
                }
-// TODO: Allow the user to select solutions!
-exit(1);
+
+               error = solver->SolveAgain();
+               if (error != B_OK)
+                       DIE(error, "failed to compute packages to install");
        }
 
        // print result
@@ -259,27 +295,45 @@ exit(1);
        if (error != B_OK)
                DIE(error, "failed to compute packages to install");
 
-       printf("The following changes will be made:\n");
+       BObjectList<BSolverPackage> packagesToActivate;
+       BObjectList<BSolverPackage> packagesToDeactivate;
+
        for (int32 i = 0; const BSolverResultElement* element = 
result.ElementAt(i);
                        i++) {
                BSolverPackage* package = element->Package();
 
                switch (element->Type()) {
                        case BSolverResultElement::B_TYPE_INSTALL:
-                               if 
(installedRepositories.HasItem(package->Repository()))
-                                       continue;
-
-                               printf("  install package %s from repository 
%s\n",
-                                       
package->Info().CanonicalFileName().String(),
-                                       package->Repository()->Name().String());
+                               if 
(!installedRepositories.HasItem(package->Repository())) {
+                                       if 
(!packagesToActivate.AddItem(package))
+                                               DIE(B_NO_MEMORY, "failed to add 
package to activate");
+                               }
                                break;
 
                        case BSolverResultElement::B_TYPE_UNINSTALL:
-                               printf("  uninstall package %s\n",
-                                       package->VersionedName().String());
+                               if (!packagesToDeactivate.AddItem(package))
+                                       DIE(B_NO_MEMORY, "failed to add package 
to deactivate");
                                break;
                }
        }
+
+       if (packagesToActivate.IsEmpty() && packagesToDeactivate.IsEmpty()) {
+               printf("Nothing to do.\n");
+               exit(0);
+       }
+
+       printf("The following changes will be made:\n");
+       for (int32 i = 0; BSolverPackage* package = 
packagesToActivate.ItemAt(i);
+               i++) {
+               printf("  install package %s from repository %s\n",
+                       package->Info().CanonicalFileName().String(),
+                       package->Repository()->Name().String());
+       }
+
+       for (int32 i = 0; BSolverPackage* package = 
packagesToDeactivate.ItemAt(i);
+               i++) {
+               printf("  uninstall package %s\n", 
package->VersionedName().String());
+       }
 // TODO: Print file/download sizes. Unfortunately our package infos don't
 // contain the file size. Which is probably correct. The file size (and 
possibly
 // other information) should, however, be provided by the repository cache in


Other related posts: