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

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

added 6 changesets to branch 'refs/remotes/HaikuPM-github/package-management'
old head: 2f028e9a2dc4b33ecac66d8fd491244a02d0f677
new head: df2685d885f3b940bc04b1cf5f39511ce6750ddf
overview: https://github.com/haiku/HaikuPM/compare/2f028e9...df2685d

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

7466fa2: pkgman install: Simplify transaction creation

c128275: <Archivable.h>: Fix conflict with BPackageKit::BPrivate
  
  ... when "using BPackageKit::BPrivate".

3ac0de3: pkgman: Refactoring -> PackageManager
  
  Move common and reusable functionality from "search" and "install" to
  new PackageManager class.

de62d76: BSolver/LibsolvSolver: Add Uninstall()
  
  Also fix incorrect check in LibsolvSolver::GetResult().

8ba41d6: pkgman install: Fix typo in usage text

df2685d: pkgman: Add "uninstall" command

                                    [ Ingo Weinhold <ingo_weinhold@xxxxxx> ]

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

10 files changed, 741 insertions(+), 440 deletions(-)
headers/os/package/solver/Solver.h        |   7 +-
headers/os/support/Archivable.h           |   4 +-
src/bin/pkgman/Jamfile                    |   2 +
src/bin/pkgman/PackageManager.cpp         | 426 ++++++++++++++++++++++++++
src/bin/pkgman/PackageManager.h           |  96 ++++++
src/bin/pkgman/command_install.cpp        | 351 +--------------------
src/bin/pkgman/command_search.cpp         |  75 +----
src/bin/pkgman/command_uninstall.cpp      |  91 ++++++
src/kits/package/solver/LibsolvSolver.cpp | 119 +++++--
src/kits/package/solver/LibsolvSolver.h   |  10 +-

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

Commit:      7466fa2d4901461dea3fc89a9229e0e04707124a
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sun Apr 21 08:36:19 2013 UTC

pkgman install: Simplify transaction creation

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

diff --git a/src/bin/pkgman/command_install.cpp 
b/src/bin/pkgman/command_install.cpp
index 0554cea..1bcbeff 100644
--- a/src/bin/pkgman/command_install.cpp
+++ b/src/bin/pkgman/command_install.cpp
@@ -357,54 +357,44 @@ InstallCommand::Execute(int argc, const char* const* argv)
                DIE(error, "failed to create transaction");
 
        // download the new packages and prepare the transaction
-       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;
-
-                               // get package URL and target entry
-                               Repository* repository
-                                       = 
static_cast<Repository*>(package->Repository());
-                               BString url = repository->Config().BaseURL();
-                               BString 
fileName(package->Info().CanonicalFileName());
-                               if (fileName.IsEmpty())
-                                       DIE(B_NO_MEMORY, "failed to allocate 
file name");
-                               url << '/' << fileName;
-
-                               BEntry entry;
-                               error = entry.SetTo(&transactionDirectory, 
fileName);
-                               if (error != B_OK)
-                                       DIE(error, "failed to create package 
entry");
+       for (int32 i = 0; BSolverPackage* package = 
packagesToActivate.ItemAt(i);
+               i++) {
+               // get package URL and target entry
+               Repository* repository
+                       = static_cast<Repository*>(package->Repository());
+               BString url = repository->Config().BaseURL();
+               BString fileName(package->Info().CanonicalFileName());
+               if (fileName.IsEmpty())
+                       DIE(B_NO_MEMORY, "failed to allocate file name");
+               url << '/' << fileName;
+
+               BEntry entry;
+               error = entry.SetTo(&transactionDirectory, fileName);
+               if (error != B_OK)
+                       DIE(error, "failed to create package entry");
 
-                               // download the package
-                               DownloadFileRequest downloadRequest(context, 
url, entry,
-                                       package->Info().Checksum());
-                               error = downloadRequest.Process();
-                               if (error != B_OK)
-                                       DIE(error, "failed to download 
package");
+               // download the package
+               DownloadFileRequest downloadRequest(context, url, entry,
+                       package->Info().Checksum());
+               error = downloadRequest.Process();
+               if (error != B_OK)
+                       DIE(error, "failed to download package");
 
-                               // add package to transaction
-                               if (!transaction.AddPackageToActivate(
-                                               
package->Info().CanonicalFileName())) {
-                                       DIE(B_NO_MEMORY,
-                                               "failed to add package to 
activate to transaction");
-                               }
-                               break;
-                       }
+               // add package to transaction
+               if (!transaction.AddPackageToActivate(
+                               package->Info().CanonicalFileName())) {
+                       DIE(B_NO_MEMORY,
+                               "failed to add package to activate to 
transaction");
+               }
+       }
 
-                       case BSolverResultElement::B_TYPE_UNINSTALL:
-                               // add package to transaction
-                               if (!transaction.AddPackageToDeactivate(
-                                               
package->Info().CanonicalFileName())) {
-                                       DIE(B_NO_MEMORY,
-                                               "failed to add package to 
deactivate to transaction");
-                               }
-                               break;
+       for (int32 i = 0; BSolverPackage* package = 
packagesToDeactivate.ItemAt(i);
+               i++) {
+               // add package to transaction
+               if (!transaction.AddPackageToDeactivate(
+                               package->Info().CanonicalFileName())) {
+                       DIE(B_NO_MEMORY,
+                               "failed to add package to deactivate to 
transaction");
                }
        }
 

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

Commit:      c128275ede0f0441de54a0f0c8bab9af7ea7460d
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sun Apr 21 10:29:41 2013 UTC

<Archivable.h>: Fix conflict with BPackageKit::BPrivate

... when "using BPackageKit::BPrivate".

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

diff --git a/headers/os/support/Archivable.h b/headers/os/support/Archivable.h
index 076a2a8..88fe3b8 100644
--- a/headers/os/support/Archivable.h
+++ b/headers/os/support/Archivable.h
@@ -21,8 +21,8 @@ namespace Archiving {
 }
 }
 
-using BPrivate::Archiving::BArchiveManager;
-using BPrivate::Archiving::BUnarchiveManager;
+using ::BPrivate::Archiving::BArchiveManager;
+using ::BPrivate::Archiving::BUnarchiveManager;
 
 
 class BArchivable {

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

Commit:      3ac0de3b1fac18912d6cb7758b502468e3802ee9
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sun Apr 21 10:31:29 2013 UTC

pkgman: Refactoring -> PackageManager

Move common and reusable functionality from "search" and "install" to
new PackageManager class.

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

diff --git a/src/bin/pkgman/Jamfile b/src/bin/pkgman/Jamfile
index cb8328a..4669d21 100644
--- a/src/bin/pkgman/Jamfile
+++ b/src/bin/pkgman/Jamfile
@@ -14,6 +14,7 @@ BinCommand pkgman :
        DecisionProvider.cpp
        JobStateListener.cpp
        PackageInfoErrorListener.cpp
+       PackageManager.cpp
        pkgman.cpp
        RepositoryBuilder.cpp
        :
diff --git a/src/bin/pkgman/PackageManager.cpp 
b/src/bin/pkgman/PackageManager.cpp
new file mode 100644
index 0000000..e099995
--- /dev/null
+++ b/src/bin/pkgman/PackageManager.cpp
@@ -0,0 +1,396 @@
+/*
+ * Copyright 2013, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Ingo Weinhold <ingo_weinhold@xxxxxx>
+ */
+
+
+#include "PackageManager.h"
+
+#include <Directory.h>
+#include <package/DownloadFileRequest.h>
+#include <package/PackageRoster.h>
+#include <package/RefreshRepositoryRequest.h>
+#include <package/solver/SolverPackage.h>
+#include <package/solver/SolverPackageSpecifier.h>
+#include <package/solver/SolverPackageSpecifierList.h>
+#include <package/solver/SolverProblem.h>
+#include <package/solver/SolverProblemSolution.h>
+#include <package/solver/SolverResult.h>
+
+#include <package/ActivationTransaction.h>
+#include <package/DaemonClient.h>
+
+#include "pkgman.h"
+#include "RepositoryBuilder.h"
+
+
+using namespace BPackageKit::BPrivate;
+
+
+// #pragma mark - Repository
+
+
+PackageManager::Repository::Repository()
+       :
+       BSolverRepository()
+{
+}
+
+
+status_t
+PackageManager::Repository::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);
+}
+
+
+const BRepositoryConfig&
+PackageManager::Repository::Config() const
+{
+       return fConfig;
+}
+
+
+// #pragma mark - Solver
+
+
+PackageManager::PackageManager(BPackageInstallationLocation location,
+       bool addInstalledRepositories, bool addOtherRepositories)
+       :
+       fLocation(location),
+       fSolver(NULL),
+       fSystemRepository(),
+       fCommonRepository(),
+       fHomeRepository(),
+       fInstalledRepositories(10),
+       fOtherRepositories(10, true),
+       fDecisionProvider(),
+       fJobStateListener(),
+       fContext(fDecisionProvider, fJobStateListener)
+{
+       // create the solver
+       status_t error = BSolver::Create(fSolver);
+       if (error != B_OK)
+               DIE(error, "failed to create solver");
+
+       // add installation location repositories
+       if (addInstalledRepositories) {
+               // We add only the repository of our actual installation 
location as the
+               // "installed" repository. The repositories for the more general
+               // installation locations are added as regular repositories, 
but with
+               // better priorities than the actual (remote) repositories. This
+               // prevents the solver from showing conflicts when a package in 
a more
+               // specific installation location overrides a package in a more 
general
+               // one. Instead any requirement that is already installed in a 
more
+               // general installation location will turn up as to be 
installed as
+               // well. But we can easily filter those out.
+               RepositoryBuilder(fSystemRepository, "system")
+                       .AddPackages(B_PACKAGE_INSTALLATION_LOCATION_SYSTEM, 
"system")
+                       .AddToSolver(fSolver, false);
+               fSystemRepository.SetPriority(-1);
+
+               bool installInHome = location == 
B_PACKAGE_INSTALLATION_LOCATION_HOME;
+               RepositoryBuilder(fCommonRepository, "common")
+                       .AddPackages(B_PACKAGE_INSTALLATION_LOCATION_COMMON, 
"common")
+                       .AddToSolver(fSolver, !installInHome);
+       
+               if (!fInstalledRepositories.AddItem(&fSystemRepository)
+                       || !fInstalledRepositories.AddItem(&fCommonRepository)) 
{
+                       DIE(B_NO_MEMORY, "failed to add installed repositories 
to list");
+               }
+       
+               if (installInHome) {
+                       fCommonRepository.SetPriority(-2);
+                       RepositoryBuilder(fHomeRepository, "home")
+                               
.AddPackages(B_PACKAGE_INSTALLATION_LOCATION_HOME, "home")
+                               .AddToSolver(fSolver, true);
+       
+                       if (!fInstalledRepositories.AddItem(&fHomeRepository))
+                               DIE(B_NO_MEMORY, "failed to add home repository 
to list");
+               }
+       }
+
+       // add other repositories
+       if (addOtherRepositories) {
+               BPackageRoster roster;
+               BStringList repositoryNames;
+               error = roster.GetRepositoryNames(repositoryNames);
+               if (error != B_OK)
+                       WARN(error, "failed to get repository names");
+       
+               int32 repositoryNameCount = repositoryNames.CountStrings();
+               for (int32 i = 0; i < repositoryNameCount; i++) {
+                       Repository* repository = new(std::nothrow) Repository;
+                       if (repository == NULL || 
!fOtherRepositories.AddItem(repository))
+                               DIE(B_NO_MEMORY, "failed to create/add 
repository object");
+       
+                       const BString& name = repositoryNames.StringAt(i);
+                       error = repository->Init(roster, fContext, name);
+                       if (error != B_OK) {
+                               WARN(error,
+                                       "failed to get config for repository 
\"%s\". Skipping.",
+                                       name.String());
+                               fOtherRepositories.RemoveItem(repository, true);
+                               continue;
+                       }
+       
+                       RepositoryBuilder(*repository, repository->Config())
+                               .AddToSolver(fSolver, false);
+               }
+       }
+}
+
+
+PackageManager::~PackageManager()
+{
+}
+
+
+void
+PackageManager::Install(const char* const* packages, int packageCount)
+{
+       // solve
+       BSolverPackageSpecifierList packagesToInstall;
+       for (int i = 0; i < packageCount; i++) {
+               if (!packagesToInstall.AppendSpecifier(packages[i]))
+                       DIE(B_NO_MEMORY, "failed to add specified package");
+       }
+
+       const BSolverPackageSpecifier* unmatchedSpecifier;
+       status_t error = fSolver->Install(packagesToInstall, 
&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 install");
+       }
+
+       _HandleProblems();
+
+       // install/uninstall packages
+       _AnalyzeResult();
+       _PrintResult();
+       _ApplyPackageChanges();
+}
+
+
+void
+PackageManager::_HandleProblems()
+{
+       while (fSolver->HasProblems()) {
+               printf("Encountered problems:\n");
+
+               int32 problemCount = fSolver->CountProblems();
+               for (int32 i = 0; i < problemCount; i++) {
+                       // print problem and possible solutions
+                       BSolverProblem* problem = fSolver->ProblemAt(i);
+                       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);
+                               int32 elementCount = solution->CountElements();
+                               for (int32 l = 0; l < elementCount; l++) {
+                                       const BSolverProblemSolutionElement* 
element
+                                               = solution->ElementAt(l);
+                                       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;
+                               }
+
+                               status_t error = 
fSolver->SelectProblemSolution(problem,
+                                       problem->SolutionAt(selected - 1));
+                               if (error != B_OK)
+                                       DIE(error, "failed to set solution");
+                               break;
+                       }
+               }
+
+               status_t error = fSolver->SolveAgain();
+               if (error != B_OK)
+                       DIE(error, "failed to compute packages to install");
+       }
+}
+
+
+void
+PackageManager::_AnalyzeResult()
+{
+       BSolverResult result;
+       status_t error = fSolver->GetResult(result);
+       if (error != B_OK)
+               DIE(error, "failed to compute packages to install");
+
+       for (int32 i = 0; const BSolverResultElement* element = 
result.ElementAt(i);
+                       i++) {
+               BSolverPackage* package = element->Package();
+
+               switch (element->Type()) {
+                       case BSolverResultElement::B_TYPE_INSTALL:
+                               if 
(!fInstalledRepositories.HasItem(package->Repository())) {
+                                       if 
(!fPackagesToActivate.AddItem(package))
+                                               DIE(B_NO_MEMORY, "failed to add 
package to activate");
+                               }
+                               break;
+
+                       case BSolverResultElement::B_TYPE_UNINSTALL:
+                               if (!fPackagesToDeactivate.AddItem(package))
+                                       DIE(B_NO_MEMORY, "failed to add package 
to deactivate");
+                               break;
+               }
+       }
+
+       if (fPackagesToActivate.IsEmpty() && fPackagesToDeactivate.IsEmpty()) {
+               printf("Nothing to do.\n");
+               exit(0);
+       }
+}
+
+
+void
+PackageManager::_PrintResult()
+{
+       printf("The following changes will be made:\n");
+       for (int32 i = 0; BSolverPackage* package = 
fPackagesToActivate.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 = 
fPackagesToDeactivate.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
+// some way. Extend BPackageInfo? Create a BPackageFileInfo?
+
+       if (!fDecisionProvider.YesNoDecisionNeeded(BString(), "Continue?", "y", 
"n",
+                       "y")) {
+               exit(1);
+       }
+}
+
+
+void
+PackageManager::_ApplyPackageChanges()
+{
+       // create an activation transaction
+       BDaemonClient daemonClient;
+       BActivationTransaction transaction;
+       BDirectory transactionDirectory;
+       status_t error = daemonClient.CreateTransaction(fLocation, transaction,
+               transactionDirectory);
+       if (error != B_OK)
+               DIE(error, "failed to create transaction");
+
+       // download the new packages and prepare the transaction
+       for (int32 i = 0; BSolverPackage* package = 
fPackagesToActivate.ItemAt(i);
+               i++) {
+               // get package URL and target entry
+               Repository* repository
+                       = static_cast<Repository*>(package->Repository());
+               BString url = repository->Config().BaseURL();
+               BString fileName(package->Info().CanonicalFileName());
+               if (fileName.IsEmpty())
+                       DIE(B_NO_MEMORY, "failed to allocate file name");
+               url << '/' << fileName;
+
+               BEntry entry;
+               error = entry.SetTo(&transactionDirectory, fileName);
+               if (error != B_OK)
+                       DIE(error, "failed to create package entry");
+
+               // download the package
+               DownloadFileRequest downloadRequest(fContext, url, entry,
+                       package->Info().Checksum());
+               error = downloadRequest.Process();
+               if (error != B_OK)
+                       DIE(error, "failed to download package");
+
+               // add package to transaction
+               if (!transaction.AddPackageToActivate(
+                               package->Info().CanonicalFileName())) {
+                       DIE(B_NO_MEMORY,
+                               "failed to add package to activate to 
transaction");
+               }
+       }
+
+       for (int32 i = 0; BSolverPackage* package = 
fPackagesToDeactivate.ItemAt(i);
+               i++) {
+               // add package to transaction
+               if (!transaction.AddPackageToDeactivate(
+                               package->Info().CanonicalFileName())) {
+                       DIE(B_NO_MEMORY,
+                               "failed to add package to deactivate to 
transaction");
+               }
+       }
+
+       // commit the transaction
+       BDaemonClient::BCommitTransactionResult transactionResult;
+       error = daemonClient.CommitTransaction(transaction, transactionResult);
+       if (error != B_OK) {
+               fprintf(stderr, "*** failed to commit transaction: %s\n",
+                       transactionResult.FullErrorMessage().String());
+               exit(1);
+       }
+
+       printf("Installation done. Old activation state backed up in \"%s\"\n",
+               transactionResult.OldStateDirectory().String());
+
+       printf("Cleaning up ...\n");
+       BEntry transactionDirectoryEntry;
+       if ((error = transactionDirectory.GetEntry(&transactionDirectoryEntry))
+                       != B_OK
+               || (error = transactionDirectoryEntry.Remove()) != B_OK) {
+               WARN(error, "failed to remove transaction directory");
+       }
+}
diff --git a/src/bin/pkgman/PackageManager.h b/src/bin/pkgman/PackageManager.h
new file mode 100644
index 0000000..7a8ebd0
--- /dev/null
+++ b/src/bin/pkgman/PackageManager.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2013, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Ingo Weinhold <ingo_weinhold@xxxxxx>
+ */
+#ifndef PACKAGE_MANAGER_H
+#define PACKAGE_MANAGER_H
+
+
+#include <ObjectList.h>
+#include <package/Context.h>
+#include <package/PackageDefs.h>
+#include <package/PackageRoster.h>
+#include <package/RepositoryConfig.h>
+#include <package/solver/Solver.h>
+#include <package/solver/SolverRepository.h>
+
+#include "DecisionProvider.h"
+#include "JobStateListener.h"
+
+
+using namespace BPackageKit;
+
+
+class PackageManager {
+public:
+                       struct Repository;
+                       typedef BObjectList<Repository> RepositoryList;
+
+public:
+                                                               PackageManager(
+                                                                       
BPackageInstallationLocation location,
+                                                                       bool 
addInstalledRepositories,
+                                                                       bool 
addOtherRepositories);
+                                                               
~PackageManager();
+
+                       BSolver*                        Solver() const
+                                                                       { 
return fSolver; }
+
+                       const BSolverRepository* SystemRepository() const
+                                                                       { 
return &fSystemRepository; }
+                       const BSolverRepository* CommonRepository() const
+                                                                       { 
return &fCommonRepository; }
+                       const BSolverRepository* HomeRepository() const
+                                                                       { 
return &fHomeRepository; }
+                       const BObjectList<BSolverRepository>& 
InstalledRepositories() const
+                                                                       { 
return fInstalledRepositories; }
+                       const RepositoryList& OtherRepositories() const
+                                                                       { 
return fOtherRepositories; }
+
+                       void                            Install(const char* 
const* packages,
+                                                                       int 
packageCount);
+
+private:
+                       typedef BObjectList<BSolverPackage> PackageList;
+
+private:
+                       void                            _HandleProblems();
+                       void                            _AnalyzeResult();
+                       void                            _PrintResult();
+                       void                            _ApplyPackageChanges();
+
+private:
+                       BPackageInstallationLocation fLocation;
+                       BSolver*                        fSolver;
+                       BSolverRepository       fSystemRepository;
+                       BSolverRepository       fCommonRepository;
+                       BSolverRepository       fHomeRepository;
+                       BObjectList<BSolverRepository> fInstalledRepositories;
+                       RepositoryList          fOtherRepositories;
+                       DecisionProvider        fDecisionProvider;
+                       JobStateListener        fJobStateListener;
+                       BContext                        fContext;
+                       PackageList                     fPackagesToActivate;
+                       PackageList                     fPackagesToDeactivate;
+};
+
+
+struct PackageManager::Repository : public BSolverRepository {
+                                                               Repository();
+
+                       status_t                        Init(BPackageRoster& 
roster, BContext& context,
+                                                                       const 
char* name);
+
+                       const BRepositoryConfig& Config() const;
+
+private:
+                       BRepositoryConfig       fConfig;
+};
+
+
+#endif // PACKAGE_MANAGER_H
diff --git a/src/bin/pkgman/command_install.cpp 
b/src/bin/pkgman/command_install.cpp
index 1bcbeff..da9c77f 100644
--- a/src/bin/pkgman/command_install.cpp
+++ b/src/bin/pkgman/command_install.cpp
@@ -7,31 +7,13 @@
  */
 
 
-#include <errno.h>
 #include <getopt.h>
 #include <stdio.h>
 #include <stdlib.h>
 
-#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>
-#include <package/solver/SolverProblem.h>
-#include <package/solver/SolverProblemSolution.h>
-#include <package/solver/SolverResult.h>
-
-#include <AutoDeleter.h>
-#include <package/ActivationTransaction.h>
-#include <package/DaemonClient.h>
-
 #include "Command.h"
-#include "DecisionProvider.h"
-#include "JobStateListener.h"
 #include "pkgman.h"
-#include "RepositoryBuilder.h"
+#include "PackageManager.h"
 
 
 // TODO: internationalization!
@@ -59,42 +41,6 @@ static const char* const kLongUsage =
 DEFINE_COMMAND(InstallCommand, "install", kShortUsage, kLongUsage)
 
 
-struct Repository : public BSolverRepository {
-       Repository()
-               :
-               BSolverRepository()
-       {
-       }
-
-       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);
-       }
-
-       const BRepositoryConfig& Config() const
-       {
-               return fConfig;
-       }
-
-private:
-       BRepositoryConfig       fConfig;
-};
-
-
 int
 InstallCommand::Execute(int argc, const char* const* argv)
 {
@@ -134,289 +80,12 @@ InstallCommand::Execute(int argc, const char* const* argv)
        int packageCount = argc - optind;
        const char* const* packages = argv + optind;
 
-       // create the solver
-       BSolver* solver;
-       status_t error = BSolver::Create(solver);
-       if (error != B_OK)
-               DIE(error, "failed to create solver");
-
-       // add repositories
-
-       // We add only the repository of our actual installation location as the
-       // "installed" repository. The repositories for the more general
-       // installation locations are added as regular repositories, but with 
better
-       // priorities than the actual (remote) repositories. This prevents the 
solver
-       // from showing conflicts when a package in a more specific installation
-       // location overrides a package in a more general one. Instead any
-       // requirement that is already installed in a more general installation
-       // location will turn up as to be installed as well. But we can easily
-       // filter those out.
-       BSolverRepository systemRepository;
-       RepositoryBuilder(systemRepository, "system")
-               .AddPackages(B_PACKAGE_INSTALLATION_LOCATION_SYSTEM, "system")
-               .AddToSolver(solver, false);
-       systemRepository.SetPriority(-1);
-
-       BSolverRepository commonRepository;
-       RepositoryBuilder(commonRepository, "common")
-               .AddPackages(B_PACKAGE_INSTALLATION_LOCATION_COMMON, "common")
-               .AddToSolver(solver, !installInHome);
-
-       BObjectList<BSolverRepository> installedRepositories(10);
-       if (!installedRepositories.AddItem(&systemRepository)
-               || !installedRepositories.AddItem(&commonRepository)) {
-               DIE(B_NO_MEMORY, "failed to add installed repositories to 
list");
-       }
-
-       BSolverRepository homeRepository;
-       if (installInHome) {
-               commonRepository.SetPriority(-2);
-               RepositoryBuilder(homeRepository, "home")
-                       .AddPackages(B_PACKAGE_INSTALLATION_LOCATION_HOME, 
"home")
-                       .AddToSolver(solver, true);
-
-               if (!installedRepositories.AddItem(&homeRepository))
-                       DIE(B_NO_MEMORY, "failed to add home repository to 
list");
-       }
-
-       // other repositories
-       DecisionProvider decisionProvider;
-       JobStateListener listener;
-       BContext context(decisionProvider, listener);
-
-       BObjectList<Repository> otherRepositories(10, true);
-       BPackageRoster roster;
-       BStringList repositoryNames;
-       error = roster.GetRepositoryNames(repositoryNames);
-       if (error != B_OK)
-               WARN(error, "failed to get repository names");
-
-       int32 repositoryNameCount = repositoryNames.CountStrings();
-       for (int32 i = 0; i < repositoryNameCount; i++) {
-               Repository* repository = new(std::nothrow) Repository;
-               if (repository == NULL || 
!otherRepositories.AddItem(repository))
-                       DIE(B_NO_MEMORY, "failed to create/add repository 
object");
-
-               const BString& name = repositoryNames.StringAt(i);
-               error = repository->Init(roster, context, name);
-               if (error != B_OK) {
-                       WARN(error, "failed to get config for repository 
\"%s\". Skipping.",
-                               name.String());
-                       otherRepositories.RemoveItem(repository, true);
-                       continue;
-               }
-
-               RepositoryBuilder(*repository, repository->Config())
-                       .AddToSolver(solver, false);
-       }
-
-       // solve
-       BSolverPackageSpecifierList packagesToInstall;
-       for (int i = 0; i < packageCount; i++) {
-               if (!packagesToInstall.AppendSpecifier(packages[i]))
-                       DIE(B_NO_MEMORY, "failed to add specified package");
-       }
-
-       const BSolverPackageSpecifier* unmatchedSpecifier;
-       error = solver->Install(packagesToInstall, &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 install");
-       }
-
-       // deal with problems
-       while (solver->HasProblems()) {
-               printf("Encountered problems:\n");
-
-               int32 problemCount = solver->CountProblems();
-               for (int32 i = 0; i < problemCount; i++) {
-                       // print problem and possible solutions
-                       BSolverProblem* problem = solver->ProblemAt(i);
-                       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);
-                               int32 elementCount = solution->CountElements();
-                               for (int32 l = 0; l < elementCount; l++) {
-                                       const BSolverProblemSolutionElement* 
element
-                                               = solution->ElementAt(l);
-                                       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;
-                       }
-               }
-
-               error = solver->SolveAgain();
-               if (error != B_OK)
-                       DIE(error, "failed to compute packages to install");
-       }
-
-       // print result
-       BSolverResult result;
-       error = solver->GetResult(result);
-       if (error != B_OK)
-               DIE(error, "failed to compute packages to install");
-
-       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())) {
-                                       if 
(!packagesToActivate.AddItem(package))
-                                               DIE(B_NO_MEMORY, "failed to add 
package to activate");
-                               }
-                               break;
-
-                       case BSolverResultElement::B_TYPE_UNINSTALL:
-                               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
-// some way. Extend BPackageInfo? Create a BPackageFileInfo?
-
-       if (!decisionProvider.YesNoDecisionNeeded(BString(), "Continue?", "y", 
"n",
-                       "y")) {
-               return 1;
-       }
-
-       // create an activation transaction
-       BDaemonClient daemonClient;
+       // perform the installation
        BPackageInstallationLocation location = installInHome
                ? B_PACKAGE_INSTALLATION_LOCATION_HOME
                : B_PACKAGE_INSTALLATION_LOCATION_COMMON;
-       BActivationTransaction transaction;
-       BDirectory transactionDirectory;
-       error = daemonClient.CreateTransaction(location, transaction,
-               transactionDirectory);
-       if (error != B_OK)
-               DIE(error, "failed to create transaction");
-
-       // download the new packages and prepare the transaction
-       for (int32 i = 0; BSolverPackage* package = 
packagesToActivate.ItemAt(i);
-               i++) {
-               // get package URL and target entry
-               Repository* repository
-                       = static_cast<Repository*>(package->Repository());
-               BString url = repository->Config().BaseURL();
-               BString fileName(package->Info().CanonicalFileName());
-               if (fileName.IsEmpty())
-                       DIE(B_NO_MEMORY, "failed to allocate file name");
-               url << '/' << fileName;
-
-               BEntry entry;
-               error = entry.SetTo(&transactionDirectory, fileName);
-               if (error != B_OK)
-                       DIE(error, "failed to create package entry");
-
-               // download the package
-               DownloadFileRequest downloadRequest(context, url, entry,
-                       package->Info().Checksum());
-               error = downloadRequest.Process();
-               if (error != B_OK)
-                       DIE(error, "failed to download package");
-
-               // add package to transaction
-               if (!transaction.AddPackageToActivate(
-                               package->Info().CanonicalFileName())) {
-                       DIE(B_NO_MEMORY,
-                               "failed to add package to activate to 
transaction");
-               }
-       }
-
-       for (int32 i = 0; BSolverPackage* package = 
packagesToDeactivate.ItemAt(i);
-               i++) {
-               // add package to transaction
-               if (!transaction.AddPackageToDeactivate(
-                               package->Info().CanonicalFileName())) {
-                       DIE(B_NO_MEMORY,
-                               "failed to add package to deactivate to 
transaction");
-               }
-       }
-
-       // commit the transaction
-       BDaemonClient::BCommitTransactionResult transactionResult;
-       error = daemonClient.CommitTransaction(transaction, transactionResult);
-       if (error != B_OK) {
-               fprintf(stderr, "*** failed to commit transaction: %s\n",
-                       transactionResult.FullErrorMessage().String());
-               exit(1);
-       }
-
-       printf("Installation done. Old activation state backed up in \"%s\"\n",
-               transactionResult.OldStateDirectory().String());
-
-       printf("Cleaning up ...\n");
-       BEntry transactionDirectoryEntry;
-       if ((error = transactionDirectory.GetEntry(&transactionDirectoryEntry))
-                       != B_OK
-               || (error = transactionDirectoryEntry.Remove()) != B_OK) {
-               WARN(error, "failed to remove transaction directory");
-       }
+       PackageManager packageManager(location, true, true);
+       packageManager.Install(packages, packageCount);
 
        return 0;
 }
diff --git a/src/bin/pkgman/command_search.cpp 
b/src/bin/pkgman/command_search.cpp
index f65db3e..9d2a72b 100644
--- a/src/bin/pkgman/command_search.cpp
+++ b/src/bin/pkgman/command_search.cpp
@@ -14,14 +14,13 @@
 #include <sys/ioctl.h>
 #include <unistd.h>
 
-#include <package/PackageRoster.h>
-#include <package/RepositoryConfig.h>
+#include <algorithm>
 
-#include <AutoDeleter.h>
+#include <package/solver/SolverPackage.h>
 
 #include "Command.h"
+#include "PackageManager.h"
 #include "pkgman.h"
-#include "RepositoryBuilder.h"
 
 
 // TODO: internationalization!
@@ -32,9 +31,6 @@
 using namespace BPackageKit;
 
 
-typedef std::map<BSolverPackage*, BString> PackagePathMap;
-
-
 static const char* const kShortUsage =
        "  %command% <search-string>\n"
        "    Searches for packages matching <search-string>.\n";
@@ -113,64 +109,13 @@ SearchCommand::Execute(int argc, const char* const* argv)
        const char* searchString = argv[optind++];
 
        // create the solver
-       BSolver* solver;
-       status_t error = BSolver::Create(solver);
-       if (error != B_OK)
-               DIE(error, "failed to create solver");
-
-       // add repositories
-
-       // installed
-       BSolverRepository systemRepository;
-       BSolverRepository commonRepository;
-       BSolverRepository homeRepository;
-       if (!uninstalledOnly) {
-               RepositoryBuilder(systemRepository, "system")
-                       .AddPackages(B_PACKAGE_INSTALLATION_LOCATION_SYSTEM, 
"system")
-                       .AddToSolver(solver, false);
-               RepositoryBuilder(commonRepository, "common")
-                       .AddPackages(B_PACKAGE_INSTALLATION_LOCATION_COMMON, 
"common")
-                       .AddToSolver(solver, false);
-//             RepositoryBuilder(homeRepository, "home")
-//                     .AddPackages(B_PACKAGE_INSTALLATION_LOCATION_HOME, 
"home")
-//                     .AddToSolver(solver, false);
-       }
-
-       // not installed
-       BObjectList<BSolverRepository> uninstalledRepositories(10, true);
-
-       if (!installedOnly) {
-               BPackageRoster roster;
-               BStringList repositoryNames;
-               error = roster.GetRepositoryNames(repositoryNames);
-               if (error != B_OK)
-                       WARN(error, "failed to get repository names");
-
-               int32 repositoryNameCount = repositoryNames.CountStrings();
-               for (int32 i = 0; i < repositoryNameCount; i++) {
-                       const BString& name = repositoryNames.StringAt(i);
-                       BRepositoryConfig config;
-                       error = roster.GetRepositoryConfig(name, &config);
-                       if (error != B_OK) {
-                               WARN(error, "failed to get config for 
repository \"%s\". "
-                                       "Skipping.", name.String());
-                               continue;
-                       }
-
-                       BSolverRepository* repository = new(std::nothrow) 
BSolverRepository;
-                       if (repository == NULL
-                               || 
!uninstalledRepositories.AddItem(repository)) {
-                               DIE(B_NO_MEMORY, "out of memory");
-                       }
-
-                       RepositoryBuilder(*repository, config)
-                               .AddToSolver(solver, false);
-               }
-       }
+       PackageManager packageManager(B_PACKAGE_INSTALLATION_LOCATION_COMMON,
+               !uninstalledOnly, !installedOnly);
+// TODO: Use B_PACKAGE_INSTALLATION_LOCATION_HOME once we actually mount it.
 
        // search
        BObjectList<BSolverPackage> packages;
-       error = solver->FindPackages(searchString,
+       status_t error = packageManager.Solver()->FindPackages(searchString,
                BSolver::B_FIND_CASE_INSENSITIVE | BSolver::B_FIND_IN_NAME
                        | BSolver::B_FIND_IN_SUMMARY | 
BSolver::B_FIND_IN_DESCRIPTION
                        | BSolver::B_FIND_IN_PROVIDES,
@@ -230,11 +175,11 @@ SearchCommand::Execute(int argc, const char* const* argv)
                BSolverPackage* package = packages.ItemAt(i);
 
                const char* installed = "";
-               if (package->Repository() == &systemRepository)
+               if (package->Repository() == packageManager.SystemRepository())
                        installed = "system";
-               else if (package->Repository() == &commonRepository)
+               else if (package->Repository() == 
packageManager.CommonRepository())
                        installed = "common";
-               else if (package->Repository() == &homeRepository)
+               else if (package->Repository() == 
packageManager.HomeRepository())
                        installed = "home";
 
                printf("%-*s  %-*s  %-*.*s\n",

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

Commit:      de62d76176c323928d2b97bc667f39850727aa1f
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sun Apr 21 10:48:39 2013 UTC

BSolver/LibsolvSolver: Add Uninstall()

Also fix incorrect check in LibsolvSolver::GetResult().

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

diff --git a/headers/os/package/solver/Solver.h 
b/headers/os/package/solver/Solver.h
index f72afff..975b008 100644
--- a/headers/os/package/solver/Solver.h
+++ b/headers/os/package/solver/Solver.h
@@ -48,8 +48,11 @@ public:
                                                                        
BObjectList<BSolverPackage>& _packages) = 0;
 
        virtual status_t                        Install(
-                                                                       const 
BSolverPackageSpecifierList&
-                                                                               
packages,
+                                                                       const 
BSolverPackageSpecifierList& packages,
+                                                                       const 
BSolverPackageSpecifier** _unmatched
+                                                                               
= NULL) = 0;
+       virtual status_t                        Uninstall(
+                                                                       const 
BSolverPackageSpecifierList& packages,
                                                                        const 
BSolverPackageSpecifier** _unmatched
                                                                                
= NULL) = 0;
        virtual status_t                        VerifyInstallation() = 0;
diff --git a/src/kits/package/solver/LibsolvSolver.cpp 
b/src/kits/package/solver/LibsolvSolver.cpp
index 2f02a27..92c98e0 100644
--- a/src/kits/package/solver/LibsolvSolver.cpp
+++ b/src/kits/package/solver/LibsolvSolver.cpp
@@ -387,7 +387,82 @@ LibsolvSolver::Install(const BSolverPackageSpecifierList& 
packages,
        // set jobs' solver mode and solve
        _SetJobsSolverMode(*fJobs, SOLVER_INSTALL);
 
-       return _Solve(false);
+       _InitSolver();
+       return _Solve();
+}
+
+
+status_t
+LibsolvSolver::Uninstall(const BSolverPackageSpecifierList& packages,
+       const BSolverPackageSpecifier** _unmatched)
+{
+       if (_unmatched != NULL)
+               *_unmatched = NULL;
+
+       if (fInstalledRepository == NULL || packages.IsEmpty())
+               return B_BAD_VALUE;
+
+       // add repositories to pool
+       status_t error = _AddRepositories();
+       if (error != B_OK)
+               return error;
+
+       // add the packages to uninstall to the job queue
+       error = _InitJobQueue();
+       if (error != B_OK)
+               return error;
+
+       int32 packageCount = packages.CountSpecifiers();
+       for (int32 i = 0; i < packageCount; i++) {
+               const BSolverPackageSpecifier& specifier = 
*packages.SpecifierAt(i);
+               switch (specifier.Type()) {
+                       case BSolverPackageSpecifier::B_UNSPECIFIED:
+                               return B_BAD_VALUE;
+
+                       case BSolverPackageSpecifier::B_PACKAGE:
+                       {
+                               BSolverPackage* package = specifier.Package();
+                               Solvable* solvable;
+                               if (package == NULL
+                                       || (solvable = _GetSolvable(package)) 
== NULL
+                                       || package->Repository()
+                                               != 
fInstalledRepository->Repository()) {
+                                       return B_BAD_VALUE;
+                               }
+
+                               queue_push2(fJobs, SOLVER_SOLVABLE,
+                                       solvable - fPool->solvables);
+                               break;
+                       }
+                       
+                       case BSolverPackageSpecifier::B_SELECT_STRING:
+                       {
+                               // find matching packages
+                               SolvQueue matchingPackages;
+               
+                               int flags = SELECTION_NAME | SELECTION_PROVIDES 
| SELECTION_GLOB
+                                       | SELECTION_CANON | SELECTION_DOTARCH | 
SELECTION_REL
+                                       | SELECTION_INSTALLED_ONLY;
+                               /*int matchFlags =*/ selection_make(fPool, 
&matchingPackages,
+                                       specifier.SelectString().String(), 
flags);
+                               if (matchingPackages.count == 0) {
+                                       if (_unmatched != NULL)
+                                               *_unmatched = &specifier;
+                                       return B_NAME_NOT_FOUND;
+                               }
+
+                               for (int j = 0; j < matchingPackages.count; j++)
+                                       queue_push(fJobs, 
matchingPackages.elements[j]);
+                       }
+               }
+       }
+
+       // set jobs' solver mode and solve
+       _SetJobsSolverMode(*fJobs, SOLVER_ERASE);
+
+       _InitSolver();
+       solver_set_flag(fSolver, SOLVER_FLAG_ALLOW_UNINSTALL, 1);
+       return _Solve();
 }
 
 
@@ -412,7 +487,8 @@ LibsolvSolver::VerifyInstallation()
        // set jobs' solver mode and solve
        _SetJobsSolverMode(*fJobs, SOLVER_VERIFY);
 
-       return _Solve(false);
+       _InitSolver();
+       return _Solve();
 }
 
 
@@ -452,7 +528,7 @@ LibsolvSolver::SolveAgain()
                        solver_take_solution(fSolver, problem->Id(), 
solution->Id(), fJobs);
        }
 
-       return _Solve(true);
+       return _Solve();
 }
 
 
@@ -505,11 +581,11 @@ LibsolvSolver::GetResult(BSolverResult& _result)
                                if (package == NULL)
                                        return B_ERROR;
 
-                               status_t error = _result.AppendElement(
-                                       
BSolverResultElement(BSolverResultElement::B_TYPE_UNINSTALL,
-                                               package));
-                               if (error != B_OK)
-                                       return error;
+                               if (!_result.AppendElement(
+                                               BSolverResultElement(
+                                                       
BSolverResultElement::B_TYPE_UNINSTALL, package))) {
+                                       return B_NO_MEMORY;
+                               }
                                break;
                        }
 
@@ -592,6 +668,17 @@ LibsolvSolver::_InitJobQueue()
 
 
 void
+LibsolvSolver::_InitSolver()
+{
+       _CleanupSolver();
+
+       fSolver = solver_create(fPool);
+       solver_set_flag(fSolver, SOLVER_FLAG_SPLITPROVIDES, 1);
+       solver_set_flag(fSolver, SOLVER_FLAG_BEST_OBEY_POLICY, 1);
+}
+
+
+void
 LibsolvSolver::_Cleanup()
 {
        _CleanupPool();
@@ -1138,23 +1225,11 @@ LibsolvSolver::_GetResolvableExpression(Id id,
 
 
 status_t
-LibsolvSolver::_Solve(bool solveAgain)
+LibsolvSolver::_Solve()
 {
-       if (fJobs == NULL)
+       if (fJobs == NULL || fSolver == 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);
-       }
-
        int problemCount = solver_solve(fSolver, fJobs);
 
        // get the problems (if any)
diff --git a/src/kits/package/solver/LibsolvSolver.h 
b/src/kits/package/solver/LibsolvSolver.h
index a4dcdd7..348be9e 100644
--- a/src/kits/package/solver/LibsolvSolver.h
+++ b/src/kits/package/solver/LibsolvSolver.h
@@ -39,8 +39,11 @@ public:
                                                                        
BObjectList<BSolverPackage>& _packages);
 
        virtual status_t                        Install(
-                                                                       const 
BSolverPackageSpecifierList&
-                                                                               
packages,
+                                                                       const 
BSolverPackageSpecifierList& packages,
+                                                                       const 
BSolverPackageSpecifier** _unmatched
+                                                                               
= NULL);
+       virtual status_t                        Uninstall(
+                                                                       const 
BSolverPackageSpecifierList& packages,
                                                                        const 
BSolverPackageSpecifier** _unmatched
                                                                                
= NULL);
        virtual status_t                        VerifyInstallation();
@@ -70,6 +73,7 @@ private:
 private:
                        status_t                        _InitPool();
                        status_t                        _InitJobQueue();
+                       void                            _InitSolver();
                        void                            _Cleanup();
                        void                            _CleanupPool();
                        void                            _CleanupJobQueue();
@@ -96,7 +100,7 @@ private:
                                                                        
BPackageResolvableExpression& _expression)
                                                                        const;
 
-                       status_t                        _Solve(bool solveAgain);
+                       status_t                        _Solve();
                        void                            
_SetJobsSolverMode(Queue& jobs, int solverMode);
 
 private:

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

Commit:      8ba41d628c0ba3fd9f694562dc8b494fbfc220f7
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sun Apr 21 10:50:31 2013 UTC

pkgman install: Fix typo in usage text

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

diff --git a/src/bin/pkgman/command_install.cpp 
b/src/bin/pkgman/command_install.cpp
index da9c77f..a1f49c7 100644
--- a/src/bin/pkgman/command_install.cpp
+++ b/src/bin/pkgman/command_install.cpp
@@ -33,7 +33,7 @@ static const char* const kLongUsage =
        "\n"
        "Options:\n"
        "  -H, --home\n"
-       "    Install the packages in the user's home directory. Default is 
to.\n"
+       "    Install the packages in the user's home directory. Default is to\n"
        "    install in the common directory.\n"
        "\n";
 

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

Commit:      df2685d885f3b940bc04b1cf5f39511ce6750ddf
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sun Apr 21 10:52:06 2013 UTC

pkgman: Add "uninstall" command

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

diff --git a/src/bin/pkgman/Jamfile b/src/bin/pkgman/Jamfile
index 4669d21..de3d08c 100644
--- a/src/bin/pkgman/Jamfile
+++ b/src/bin/pkgman/Jamfile
@@ -11,6 +11,7 @@ BinCommand pkgman :
        command_refresh.cpp
        command_resolve_dependencies.cpp
        command_search.cpp
+       command_uninstall.cpp
        DecisionProvider.cpp
        JobStateListener.cpp
        PackageInfoErrorListener.cpp
diff --git a/src/bin/pkgman/PackageManager.cpp 
b/src/bin/pkgman/PackageManager.cpp
index e099995..f587451 100644
--- a/src/bin/pkgman/PackageManager.cpp
+++ b/src/bin/pkgman/PackageManager.cpp
@@ -194,6 +194,36 @@ PackageManager::Install(const char* const* packages, int 
packageCount)
 
 
 void
+PackageManager::Uninstall(const char* const* packages, int packageCount)
+{
+       // solve
+       BSolverPackageSpecifierList packagesToUninstall;
+       for (int i = 0; i < packageCount; i++) {
+               if (!packagesToUninstall.AppendSpecifier(packages[i]))
+                       DIE(B_NO_MEMORY, "failed to add specified package");
+       }
+
+       const BSolverPackageSpecifier* unmatchedSpecifier;
+       status_t error = fSolver->Uninstall(packagesToUninstall,
+               &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");
+       }
+
+       _HandleProblems();
+
+       // install/uninstall packages
+       _AnalyzeResult();
+       _PrintResult();
+       _ApplyPackageChanges();
+}
+
+
+void
 PackageManager::_HandleProblems()
 {
        while (fSolver->HasProblems()) {
@@ -254,7 +284,7 @@ PackageManager::_HandleProblems()
 
                status_t error = fSolver->SolveAgain();
                if (error != B_OK)
-                       DIE(error, "failed to compute packages to install");
+                       DIE(error, "failed to recompute packages to 
un/-install");
        }
 }
 
@@ -265,7 +295,7 @@ PackageManager::_AnalyzeResult()
        BSolverResult result;
        status_t error = fSolver->GetResult(result);
        if (error != B_OK)
-               DIE(error, "failed to compute packages to install");
+               DIE(error, "failed to compute packages to un/-install");
 
        for (int32 i = 0; const BSolverResultElement* element = 
result.ElementAt(i);
                        i++) {
diff --git a/src/bin/pkgman/PackageManager.h b/src/bin/pkgman/PackageManager.h
index 7a8ebd0..ca9b3a0 100644
--- a/src/bin/pkgman/PackageManager.h
+++ b/src/bin/pkgman/PackageManager.h
@@ -52,6 +52,8 @@ public:
 
                        void                            Install(const char* 
const* packages,
                                                                        int 
packageCount);
+                       void                            Uninstall(const char* 
const* packages,
+                                                                       int 
packageCount);
 
 private:
                        typedef BObjectList<BSolverPackage> PackageList;
diff --git a/src/bin/pkgman/command_uninstall.cpp 
b/src/bin/pkgman/command_uninstall.cpp
new file mode 100644
index 0000000..5743603
--- /dev/null
+++ b/src/bin/pkgman/command_uninstall.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2013, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Ingo Weinhold <ingo_weinhold@xxxxxx>
+ */
+
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "Command.h"
+#include "pkgman.h"
+#include "PackageManager.h"
+
+
+// TODO: internationalization!
+
+
+using namespace BPackageKit;
+using namespace BPackageKit::BPrivate;
+
+
+static const char* const kShortUsage =
+       "  %command% <package> ...\n"
+       "    Uninstalls one or more packages.\n";
+
+static const char* const kLongUsage =
+       "Usage: %program% %command% <package> ...\n"
+       "Uninstalls the specified packages.\n"
+       "\n"
+       "Options:\n"
+       "  -H, --home\n"
+       "    Uninstall the packages from the user's home directory. Default is 
to\n"
+       "    uninstall from the common directory.\n"
+       "\n";
+
+
+DEFINE_COMMAND(UninstallCommand, "uninstall", kShortUsage, kLongUsage)
+
+
+int
+UninstallCommand::Execute(int argc, const char* const* argv)
+{
+       bool uninstallFromHome = false;
+
+       while (true) {
+               static struct option sLongOptions[] = {
+                       { "help", no_argument, 0, 'h' },
+                       { "home", no_argument, 0, 'H' },
+                       { 0, 0, 0, 0 }
+               };
+
+               opterr = 0; // don't print errors
+               int c = getopt_long(argc, (char**)argv, "hu", sLongOptions, 
NULL);
+               if (c == -1)
+                       break;
+
+               switch (c) {
+                       case 'h':
+                               PrintUsageAndExit(false);
+                               break;
+
+                       case 'H':
+                               uninstallFromHome = true;
+                               break;
+
+                       default:
+                               PrintUsageAndExit(true);
+                               break;
+               }
+       }
+
+       // The remaining arguments are the packages to be uninstalled.
+       if (argc < optind + 1)
+               PrintUsageAndExit(true);
+
+       int packageCount = argc - optind;
+       const char* const* packages = argv + optind;
+
+       // perform the installation
+       BPackageInstallationLocation location = uninstallFromHome
+               ? B_PACKAGE_INSTALLATION_LOCATION_HOME
+               : B_PACKAGE_INSTALLATION_LOCATION_COMMON;
+       PackageManager packageManager(location, true, true);
+       packageManager.Uninstall(packages, packageCount);
+
+       return 0;
+}


Other related posts:

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