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

  • From: HaikuPM-github.package-management <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 12 Apr 2013 02:00:33 +0200 (CEST)

added 2 changesets to branch 'refs/remotes/HaikuPM-github/package-management'
old head: 663e351cb468e889ffcd08c07fc867b3002a1c91
new head: 38e528bbc1c368456c8b8a94d6f21081934cc4f9
overview: https://github.com/haiku/HaikuPM/compare/663e351...38e528b

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

01758ed: Rework SolverPackageSpecifier
  
  * It no longer consists of a BPackageResolvableExpression and a
    repository. Instead it can now either refer to a package directly or
    consist of a search string.
  * SolverPackageSpecifierList: Add AppendSpecifier() convenience
    versions.
  * Adjust LibsolvSolver and pkgman accordingly.

38e528b: pkgman: C++-ify the command handling
  
  There's now a Command class that must be derived and registered with
  a CommandManager, all simplified by a REGISTER_COMMAND macro. That gets
  rid of the print_command_usage_and_exit() function copy for every
  command, moves the short usage texts to the command implementations,
  and avoids any repetition of the command name. When implementing a new
  command only a new source file needs to be created, nothing else needs
  to be touched.

                                    [ Ingo Weinhold <ingo_weinhold@xxxxxx> ]

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

17 files changed, 425 insertions(+), 197 deletions(-)
.../os/package/solver/SolverPackageSpecifier.h   |  32 +++---
.../package/solver/SolverPackageSpecifierList.h  |   5 +-
src/bin/pkgman/Command.cpp                       | 107 +++++++++++++++++++
src/bin/pkgman/Command.h                         |  86 +++++++++++++++
src/bin/pkgman/Jamfile                           |   1 +
src/bin/pkgman/command_add_repo.cpp              |  27 +++--
src/bin/pkgman/command_drop_repo.cpp             |  27 +++--
src/bin/pkgman/command_list_repos.cpp            |  27 +++--
src/bin/pkgman/command_refresh.cpp               |  26 ++---
src/bin/pkgman/command_resolve_dependencies.cpp  |  34 +++---
src/bin/pkgman/command_search.cpp                |  27 +++--
src/bin/pkgman/pkgman.cpp                        |  62 ++++-------
src/bin/pkgman/pkgman.h                          |   6 --
src/kits/package/solver/LibsolvSolver.cpp        |  88 ++++++++++-----
src/kits/package/solver/LibsolvSolver.h          |   3 +
.../package/solver/SolverPackageSpecifier.cpp    |  50 +++++----
.../solver/SolverPackageSpecifierList.cpp        |  14 +++

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

Commit:      01758ed3323e22359f685ffb37ef42a3b856fd66
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Thu Apr 11 22:21:49 2013 UTC

Rework SolverPackageSpecifier

* It no longer consists of a BPackageResolvableExpression and a
  repository. Instead it can now either refer to a package directly or
  consist of a search string.
* SolverPackageSpecifierList: Add AppendSpecifier() convenience
  versions.
* Adjust LibsolvSolver and pkgman accordingly.

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

diff --git a/headers/os/package/solver/SolverPackageSpecifier.h 
b/headers/os/package/solver/SolverPackageSpecifier.h
index cfef584..0f4dd89 100644
--- a/headers/os/package/solver/SolverPackageSpecifier.h
+++ b/headers/os/package/solver/SolverPackageSpecifier.h
@@ -6,38 +6,44 @@
 #define _PACKAGE__SOLVER_PACKAGE_SPECIFIER_H_
 
 
-#include <package/PackageResolvableExpression.h>
+#include <String.h>
 
 
 namespace BPackageKit {
 
 
-class BSolverRepository;
+class BSolverPackage;
 
 
 class BSolverPackageSpecifier {
 public:
+                       enum BType {
+                               B_UNSPECIFIED,
+                               B_PACKAGE,
+                               B_SELECT_STRING
+                       };
+
+public:
                                                                
BSolverPackageSpecifier();
-                                                               
BSolverPackageSpecifier(
-                                                                       const 
BPackageResolvableExpression&
-                                                                               
expression);
-                                                               
BSolverPackageSpecifier(
-                                                                       
BSolverRepository* repository,
-                                                                       const 
BPackageResolvableExpression&
-                                                                               
expression);
+       explicit                                        BSolverPackageSpecifier(
+                                                                       
BSolverPackage* package);
+       explicit                                        BSolverPackageSpecifier(
+                                                                       const 
BString& selectString);
                                                                
BSolverPackageSpecifier(
                                                                        const 
BSolverPackageSpecifier& other);
                                                                
~BSolverPackageSpecifier();
 
-                       BSolverRepository*      Repository() const;
-                       const BPackageResolvableExpression& Expression() const;
+                       BType                           Type() const;
+                       BSolverPackage*         Package() const;
+                       const BString&          SelectString() const;
 
                        BSolverPackageSpecifier& operator=(
                                                                        const 
BSolverPackageSpecifier& other);
 
 private:
-                       BSolverRepository*      fRepository;
-                       BPackageResolvableExpression fExpression;
+                       BType                           fType;
+                       BSolverPackage*         fPackage;
+                       BString                         fSelectString;
 };
 
 
diff --git a/headers/os/package/solver/SolverPackageSpecifierList.h 
b/headers/os/package/solver/SolverPackageSpecifierList.h
index 7a2bf58..9a4d582 100644
--- a/headers/os/package/solver/SolverPackageSpecifierList.h
+++ b/headers/os/package/solver/SolverPackageSpecifierList.h
@@ -6,12 +6,13 @@
 #define _PACKAGE__SOLVER_PACKAGE_SPECIFIER_LIST_H_
 
 
-#include <SupportDefs.h>
+#include <String.h>
 
 
 namespace BPackageKit {
 
 
+class BSolverPackage;
 class BSolverPackageSpecifier;
 
 
@@ -28,6 +29,8 @@ public:
 
                        bool                            AppendSpecifier(
                                                                        const 
BSolverPackageSpecifier& specifier);
+                       bool                            
AppendSpecifier(BSolverPackage* package);
+                       bool                            AppendSpecifier(const 
BString& selectString);
                        void                            MakeEmpty();
 
                        BSolverPackageSpecifierList& operator=(
diff --git a/src/bin/pkgman/command_resolve_dependencies.cpp 
b/src/bin/pkgman/command_resolve_dependencies.cpp
index 9e67ced..e585f6d 100644
--- a/src/bin/pkgman/command_resolve_dependencies.cpp
+++ b/src/bin/pkgman/command_resolve_dependencies.cpp
@@ -182,12 +182,8 @@ command_resolve_dependencies(int argc, const char* const* 
argv)
 
        // resolve
        BSolverPackageSpecifierList packagesToInstall;
-       if (!packagesToInstall.AppendSpecifier(
-                       BSolverPackageSpecifier(&dummyRepository,
-                               BPackageResolvableExpression(
-                                       specifiedPackage->Info().Name())))) {
+       if (!packagesToInstall.AppendSpecifier(specifiedPackage))
                DIE(B_NO_MEMORY, "failed to add specified package");
-       }
 
        error = solver->Install(packagesToInstall);
        if (error != B_OK)
diff --git a/src/kits/package/solver/LibsolvSolver.cpp 
b/src/kits/package/solver/LibsolvSolver.cpp
index 66c3a78..a8efa8e 100644
--- a/src/kits/package/solver/LibsolvSolver.cpp
+++ b/src/kits/package/solver/LibsolvSolver.cpp
@@ -162,6 +162,7 @@ LibsolvSolver::LibsolvSolver()
        fRepositoryInfos(10, true),
        fInstalledRepository(NULL),
        fSolvablePackages(),
+       fPackageSolvables(),
        fProblems(10, true)
 {
 }
@@ -299,38 +300,61 @@ LibsolvSolver::Install(const BSolverPackageSpecifierList& 
packages)
        int32 packageCount = packages.CountSpecifiers();
        for (int32 i = 0; i < packageCount; i++) {
                const BSolverPackageSpecifier& specifier = 
*packages.SpecifierAt(i);
-
-               // find matching packages
-               SolvQueue matchingPackages;
-
-               int flags = SELECTION_NAME | SELECTION_PROVIDES | SELECTION_GLOB
-                       | SELECTION_CANON | SELECTION_DOTARCH | SELECTION_REL;
-// TODO: All flags needed/useful?
-               /*int matchFlags =*/ selection_make(fPool, &matchingPackages,
-                       specifier.Expression().Name(), flags);
-// TODO: Don't just match the name, but also the version, if given!
-               if (matchingPackages.count == 0)
-                       return B_NAME_NOT_FOUND;
-
-               // restrict to the matching repository
-               if (BSolverRepository* repository = specifier.Repository()) {
-                       RepositoryInfo* repositoryInfo = 
_GetRepositoryInfo(repository);
-                       if (repositoryInfo == NULL)
+               switch (specifier.Type()) {
+                       case BSolverPackageSpecifier::B_UNSPECIFIED:
                                return B_BAD_VALUE;
 
-                       SolvQueue repoFilter;
-                       queue_push2(&repoFilter,
-                               SOLVER_SOLVABLE_REPO/* | SOLVER_SETREPO | 
SOLVER_SETVENDOR*/,
-                               repositoryInfo->SolvRepo()->repoid);
+                       case BSolverPackageSpecifier::B_PACKAGE:
+                       {
+                               BSolverPackage* package = specifier.Package();
+                               Solvable* solvable;
+                               if (package == NULL
+                                       || (solvable = _GetSolvable(package)) 
== NULL) {
+                                       return B_BAD_VALUE;
+                               }
 
-                       selection_filter(fPool, &matchingPackages, &repoFilter);
+                               queue_push2(&jobs, SOLVER_SOLVABLE,
+                                       fPool->solvables - solvable);
+                               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;
+                               /*int matchFlags =*/ selection_make(fPool, 
&matchingPackages,
+                                       specifier.SelectString().String(), 
flags);
+                               if (matchingPackages.count == 0)
+                                       return B_NAME_NOT_FOUND;
+// TODO: We might want to add support for restricting to certain repositories.
+#if 0          
+                               // restrict to the matching repository
+                               if (BSolverRepository* repository = 
specifier.Repository()) {
+                                       RepositoryInfo* repositoryInfo
+                                               = 
_GetRepositoryInfo(repository);
+                                       if (repositoryInfo == NULL)
+                                               return B_BAD_VALUE;
+
+                                       SolvQueue repoFilter;
+                                       queue_push2(&repoFilter,
+                                               SOLVER_SOLVABLE_REPO
+                                                       /* | SOLVER_SETREPO | 
SOLVER_SETVENDOR*/,
+                                               
repositoryInfo->SolvRepo()->repoid);
+
+                                       selection_filter(fPool, 
&matchingPackages, &repoFilter);
+
+                                       if (matchingPackages.count == 0)
+                                               return B_NAME_NOT_FOUND;
+                               }
+#endif
 
-                       if (matchingPackages.count == 0)
-                               return B_NAME_NOT_FOUND;
+                               for (int j = 0; j < matchingPackages.count; j++)
+                                       queue_push(&jobs, 
matchingPackages.elements[j]);
+                       }
                }
-
-               for (int j = 0; j < matchingPackages.count; j++)
-                       queue_push(&jobs, matchingPackages.elements[j]);
        }
 
        // set jobs' solver mode and solve
@@ -506,6 +530,7 @@ LibsolvSolver::_CleanupPool()
 
        // clean up our data structures that depend on/refer to libsolv pool 
data
        fSolvablePackages.clear();
+       fPackageSolvables.clear();
 
        int32 repositoryCount = fRepositoryInfos.CountItems();
        for (int32 i = 0; i < repositoryCount; i++)
@@ -575,6 +600,7 @@ LibsolvSolver::_AddRepositories()
 
                        try {
                                fSolvablePackages[solvable] = package;
+                               fPackageSolvables[package] = solvable;
                        } catch (std::bad_alloc&) {
                                return B_NO_MEMORY;
                        }
@@ -625,6 +651,14 @@ LibsolvSolver::_GetPackage(Id solvableId) const
 }
 
 
+Solvable*
+LibsolvSolver::_GetSolvable(BSolverPackage* package) const
+{
+       PackageMap::const_iterator it = fPackageSolvables.find(package);
+       return it != fPackageSolvables.end() ? it->second : NULL;
+}
+
+
 status_t
 LibsolvSolver::_AddProblem(Id problemId)
 {
diff --git a/src/kits/package/solver/LibsolvSolver.h 
b/src/kits/package/solver/LibsolvSolver.h
index eaecd8f..48f76f8 100644
--- a/src/kits/package/solver/LibsolvSolver.h
+++ b/src/kits/package/solver/LibsolvSolver.h
@@ -58,6 +58,7 @@ private:
                        typedef BObjectList<RepositoryInfo> RepositoryInfoList;
                        typedef BObjectList<Problem> ProblemList;
                        typedef std::map<Solvable*, BSolverPackage*> 
SolvableMap;
+                       typedef std::map<BSolverPackage*, Solvable*> PackageMap;
 
 private:
                        status_t                        _InitPool();
@@ -71,6 +72,7 @@ private:
                                                                        
BSolverRepository* repository) const;
                        BSolverPackage*         _GetPackage(Solvable* solvable) 
const;
                        BSolverPackage*         _GetPackage(Id solvableId) 
const;
+                       Solvable*                       
_GetSolvable(BSolverPackage* package) const;
 
                        status_t                        _AddProblem(Id 
problemId);
                        status_t                        _AddSolution(Problem* 
problem, Id solutionId);
@@ -94,6 +96,7 @@ private:
                        RepositoryInfoList      fRepositoryInfos;
                        RepositoryInfo*         fInstalledRepository;
                        SolvableMap                     fSolvablePackages;
+                       PackageMap                      fPackageSolvables;
                        ProblemList                     fProblems;
 };
 
diff --git a/src/kits/package/solver/SolverPackageSpecifier.cpp 
b/src/kits/package/solver/SolverPackageSpecifier.cpp
index c1469d4..1e3b61d 100644
--- a/src/kits/package/solver/SolverPackageSpecifier.cpp
+++ b/src/kits/package/solver/SolverPackageSpecifier.cpp
@@ -15,26 +15,27 @@ namespace BPackageKit {
 
 BSolverPackageSpecifier::BSolverPackageSpecifier()
        :
-       fRepository(NULL),
-       fExpression()
+       fType(B_UNSPECIFIED),
+       fPackage(NULL),
+       fSelectString()
 {
 }
 
 
-BSolverPackageSpecifier::BSolverPackageSpecifier(
-       const BPackageResolvableExpression& expression)
+BSolverPackageSpecifier::BSolverPackageSpecifier(BSolverPackage* package)
        :
-       fRepository(NULL),
-       fExpression(expression)
+       fType(B_PACKAGE),
+       fPackage(package),
+       fSelectString()
 {
 }
 
 
-BSolverPackageSpecifier::BSolverPackageSpecifier(BSolverRepository* repository,
-       const BPackageResolvableExpression& expression)
+BSolverPackageSpecifier::BSolverPackageSpecifier(const BString& selectString)
        :
-       fRepository(repository),
-       fExpression(expression)
+       fType(B_SELECT_STRING),
+       fPackage(NULL),
+       fSelectString()
 {
 }
 
@@ -42,8 +43,9 @@ 
BSolverPackageSpecifier::BSolverPackageSpecifier(BSolverRepository* repository,
 BSolverPackageSpecifier::BSolverPackageSpecifier(
        const BSolverPackageSpecifier& other)
        :
-       fRepository(other.fRepository),
-       fExpression(other.fExpression)
+       fType(other.fType),
+       fPackage(other.fPackage),
+       fSelectString(other.fSelectString)
 {
 }
 
@@ -53,25 +55,33 @@ BSolverPackageSpecifier::~BSolverPackageSpecifier()
 }
 
 
-BSolverRepository*
-BSolverPackageSpecifier::Repository() const
+BSolverPackageSpecifier::BType
+BSolverPackageSpecifier::Type() const
+{
+       return fType;
+}
+
+
+BSolverPackage*
+BSolverPackageSpecifier::Package() const
 {
-       return fRepository;
+       return fPackage;
 }
 
 
-const BPackageResolvableExpression&
-BSolverPackageSpecifier::Expression() const
+const BString&
+BSolverPackageSpecifier::SelectString() const
 {
-       return fExpression;
+       return fSelectString;
 }
 
 
 BSolverPackageSpecifier&
 BSolverPackageSpecifier::operator=(const BSolverPackageSpecifier& other)
 {
-       fRepository = other.fRepository;
-       fExpression = other.fExpression;
+       fType = other.fType;
+       fPackage = other.fPackage;
+       fSelectString = other.fSelectString;
        return *this;
 }
 
diff --git a/src/kits/package/solver/SolverPackageSpecifierList.cpp 
b/src/kits/package/solver/SolverPackageSpecifierList.cpp
index 6544179..69a9683 100644
--- a/src/kits/package/solver/SolverPackageSpecifierList.cpp
+++ b/src/kits/package/solver/SolverPackageSpecifierList.cpp
@@ -101,6 +101,20 @@ BSolverPackageSpecifierList::AppendSpecifier(
 }
 
 
+bool
+BSolverPackageSpecifierList::AppendSpecifier(BSolverPackage* package)
+{
+       return AppendSpecifier(BSolverPackageSpecifier(package));
+}
+
+
+bool
+BSolverPackageSpecifierList::AppendSpecifier(const BString& selectString)
+{
+       return AppendSpecifier(BSolverPackageSpecifier(selectString));
+}
+
+
 void
 BSolverPackageSpecifierList::MakeEmpty()
 {

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

Commit:      38e528bbc1c368456c8b8a94d6f21081934cc4f9
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Thu Apr 11 23:48:53 2013 UTC

pkgman: C++-ify the command handling

There's now a Command class that must be derived and registered with
a CommandManager, all simplified by a REGISTER_COMMAND macro. That gets
rid of the print_command_usage_and_exit() function copy for every
command, moves the short usage texts to the command implementations,
and avoids any repetition of the command name. When implementing a new
command only a new source file needs to be created, nothing else needs
to be touched.

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

diff --git a/src/bin/pkgman/Command.cpp b/src/bin/pkgman/Command.cpp
new file mode 100644
index 0000000..31c4b48
--- /dev/null
+++ b/src/bin/pkgman/Command.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2013, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Ingo Weinhold <ingo_weinhold@xxxxxx>
+ */
+
+
+#include "Command.h"
+
+#include <stdio.h>
+
+
+static int
+compare_commands_by_name(const Command* a, const Command* b)
+{
+       return a->Name().Compare(b->Name());
+}
+
+
+// #pragma mark - Command
+
+
+Command::Command(const BString& name, const BString& shortUsage,
+       const BString& longUsage)
+       :
+       fName(name),
+       fShortUsage(shortUsage),
+       fLongUsage(longUsage)
+{
+       fShortUsage.ReplaceAll("%command%", fName);
+       fLongUsage.ReplaceAll("%command%", fName);
+}
+
+
+Command::~Command()
+{
+}
+
+
+void
+Command::Init(const char* programName)
+{
+       fShortUsage.ReplaceAll("%program%", programName);
+       fLongUsage.ReplaceAll("%program%", programName);
+}
+
+
+void
+Command::PrintUsage(bool error) const
+{
+       fprintf(error ? stderr : stdout, "%s", fLongUsage.String());
+}
+
+
+void
+Command::PrintUsageAndExit(bool error) const
+{
+       PrintUsage(error);
+       exit(error ? 1 : 0);
+}
+
+
+// #pragma mark - CommandManager
+
+
+/*static*/ CommandManager*
+CommandManager::Default()
+{
+       static CommandManager* manager = new CommandManager;
+       return manager;
+}
+
+
+void
+CommandManager::RegisterCommand(Command* command)
+{
+       fCommands.AddItem(command);
+}
+
+
+void
+CommandManager::InitCommands(const char* programName)
+{
+       for (int32 i = 0; Command* command = fCommands.ItemAt(i); i++)
+               command->Init(programName);
+
+       fCommands.SortItems(&compare_commands_by_name);
+}
+
+
+void
+CommandManager::GetCommands(const char* prefix, CommandList& _commands)
+{
+       for (int32 i = 0; Command* command = fCommands.ItemAt(i); i++) {
+               if (command->Name().StartsWith(prefix))
+                       _commands.AddItem(command);
+       }
+}
+
+
+CommandManager::CommandManager()
+       :
+       fCommands(20, true)
+{
+}
diff --git a/src/bin/pkgman/Command.h b/src/bin/pkgman/Command.h
new file mode 100644
index 0000000..4d9c6cc
--- /dev/null
+++ b/src/bin/pkgman/Command.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2013, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Ingo Weinhold <ingo_weinhold@xxxxxx>
+ */
+#ifndef COMMAND_H
+#define COMMAND_H
+
+
+#include <ObjectList.h>
+#include <String.h>
+
+
+class Command {
+public:
+                                                               Command(const 
BString& name,
+                                                                       const 
BString& shortUsage,
+                                                                       const 
BString& longUsage);
+       virtual                                         ~Command();
+
+                       void                            Init(const char* 
programName);
+
+                       const BString&          Name() const            { 
return fName; }
+                       const BString&          ShortUsage() const      { 
return fShortUsage; }
+                       const BString&          LongUsage() const       { 
return fName; }
+
+                       void                            PrintUsage(bool error) 
const;
+                       void                            PrintUsageAndExit(bool 
error) const;
+
+       virtual int                                     Execute(int argc, const 
char* const* argv) = 0;
+
+private:
+                       BString                         fName;
+                       BString                         fShortUsage;
+                       BString                         fLongUsage;
+};
+
+
+typedef BObjectList<Command> CommandList;
+
+
+class CommandManager {
+public:
+       static  CommandManager*         Default();
+
+                       void                            
RegisterCommand(Command* command);
+                       void                            InitCommands(const 
char* programName);
+
+                       const CommandList&      Commands() const
+                                                                       { 
return fCommands; }
+                       void                            GetCommands(const char* 
prefix,
+                                                                       
CommandList& _commands);
+
+private:
+                                                               
CommandManager();
+
+private:
+                       CommandList                     fCommands;
+};
+
+
+template<typename CommandType>
+struct CommandRegistrar {
+       CommandRegistrar()
+       {
+               CommandManager::Default()->RegisterCommand(new CommandType);
+       }
+};
+
+
+#define DEFINE_COMMAND(className, name, shortUsage, longUsage) \
+       struct className : Command {                                            
                \
+               className()                                                     
                                        \
+                       :                                                       
                                                \
+                       Command(name, shortUsage, longUsage)                    
        \
+               {                                                               
                                                \
+               }                                                               
                                                \
+                                                                               
                                                \
+               virtual int Execute(int argc, const char* const* argv); \
+       };                                                                      
                                                \
+       static CommandRegistrar<className> sRegister##className;
+
+
+#endif // COMMAND_H
diff --git a/src/bin/pkgman/Jamfile b/src/bin/pkgman/Jamfile
index de9b873..c985ecf 100644
--- a/src/bin/pkgman/Jamfile
+++ b/src/bin/pkgman/Jamfile
@@ -3,6 +3,7 @@ SubDir HAIKU_TOP src bin pkgman ;
 UsePrivateHeaders shared support ;
 
 BinCommand pkgman :
+       Command.cpp
        command_add_repo.cpp
        command_drop_repo.cpp
        command_list_repos.cpp
diff --git a/src/bin/pkgman/command_add_repo.cpp 
b/src/bin/pkgman/command_add_repo.cpp
index ba34b52..b63583b 100644
--- a/src/bin/pkgman/command_add_repo.cpp
+++ b/src/bin/pkgman/command_add_repo.cpp
@@ -16,6 +16,7 @@
 #include <package/RefreshRepositoryRequest.h>
 #include <package/PackageRoster.h>
 
+#include "Command.h"
 #include "DecisionProvider.h"
 #include "JobStateListener.h"
 #include "pkgman.h"
@@ -27,23 +28,21 @@ using namespace BPackageKit;
 // TODO: internationalization!
 
 
-static const char* kCommandUsage =
-       "Usage: %s add-repo <repo-URL> [<repo-URL> ...]\n"
+static const char* const kShortUsage =
+       "  %command% <repo-base-url>\n"
+       "    Adds the repository with the given <repo-base-URL>.\n";
+
+static const char* const kLongUsage =
+       "Usage: %program% %command% <repo-URL> [<repo-URL> ...]\n"
        "Adds one or more repositories by downloading them from the given 
URL(s).\n"
-       "\n"
-;
+       "\n";
 
 
-static void
-print_command_usage_and_exit(bool error)
-{
-    fprintf(error ? stderr : stdout, kCommandUsage, kProgramName);
-    exit(error ? 1 : 0);
-}
+DEFINE_COMMAND(AddRepoCommand, "add-repo", kShortUsage, kLongUsage)
 
 
 int
-command_add_repo(int argc, const char* const* argv)
+AddRepoCommand::Execute(int argc, const char* const* argv)
 {
        bool asUserRepository = false;
 
@@ -61,7 +60,7 @@ command_add_repo(int argc, const char* const* argv)
 
                switch (c) {
                        case 'h':
-                               print_command_usage_and_exit(false);
+                               PrintUsageAndExit(false);
                                break;
 
                        case 'u':
@@ -69,14 +68,14 @@ command_add_repo(int argc, const char* const* argv)
                                break;
 
                        default:
-                               print_command_usage_and_exit(true);
+                               PrintUsageAndExit(true);
                                break;
                }
        }
 
        // The remaining arguments are repo URLs, i. e. at least one more 
argument.
        if (argc < optind + 1)
-               print_command_usage_and_exit(true);
+               PrintUsageAndExit(true);
 
        const char* const* repoURLs = argv + optind;
        int urlCount = argc - optind;
diff --git a/src/bin/pkgman/command_drop_repo.cpp 
b/src/bin/pkgman/command_drop_repo.cpp
index fecdd87..e026757 100644
--- a/src/bin/pkgman/command_drop_repo.cpp
+++ b/src/bin/pkgman/command_drop_repo.cpp
@@ -14,6 +14,7 @@
 #include <package/DropRepositoryRequest.h>
 #include <package/Context.h>
 
+#include "Command.h"
 #include "DecisionProvider.h"
 #include "JobStateListener.h"
 #include "pkgman.h"
@@ -25,23 +26,21 @@ using namespace BPackageKit;
 // TODO: internationalization!
 
 
-static const char* kCommandUsage =
-       "Usage: %s drop-repo <repo-name>\n"
+static const char* const kShortUsage =
+       "  %command% <repo-name>\n"
+       "    Drops the repository with the given <repo-name>.\n";
+
+static const char* const kLongUsage =
+       "Usage: %program% %command% <repo-name>\n"
        "Drops (i.e. removes) the repository with the given name.\n"
-       "\n"
-;
+       "\n";
 
 
-static void
-print_command_usage_and_exit(bool error)
-{
-    fprintf(error ? stderr : stdout, kCommandUsage, kProgramName);
-    exit(error ? 1 : 0);
-}
+DEFINE_COMMAND(DropRepoCommand, "drop-repo", kShortUsage, kLongUsage)
 
 
 int
-command_drop_repo(int argc, const char* const* argv)
+DropRepoCommand::Execute(int argc, const char* const* argv)
 {
        bool yesMode = false;
 
@@ -59,7 +58,7 @@ command_drop_repo(int argc, const char* const* argv)
 
                switch (c) {
                        case 'h':
-                               print_command_usage_and_exit(false);
+                               PrintUsageAndExit(false);
                                break;
 
                        case 'y':
@@ -67,14 +66,14 @@ command_drop_repo(int argc, const char* const* argv)
                                break;
 
                        default:
-                               print_command_usage_and_exit(true);
+                               PrintUsageAndExit(true);
                                break;
                }
        }
 
        // The remaining argument is a repo name, i. e. one more argument.
        if (argc != optind + 1)
-               print_command_usage_and_exit(true);
+               PrintUsageAndExit(true);
 
        const char* repoName = argv[optind];
 
diff --git a/src/bin/pkgman/command_list_repos.cpp 
b/src/bin/pkgman/command_list_repos.cpp
index 244404d..e046512 100644
--- a/src/bin/pkgman/command_list_repos.cpp
+++ b/src/bin/pkgman/command_list_repos.cpp
@@ -21,6 +21,7 @@
 #include <package/PackageRoster.h>
 #include <package/RepositoryInfo.h>
 
+#include "Command.h"
 #include "pkgman.h"
 
 
@@ -30,24 +31,22 @@
 using namespace BPackageKit;
 
 
-static const char* kCommandUsage =
+static const char* const kShortUsage =
+       "  %command%\n"
+       "    Lists all repositories.\n";
+
+static const char* const kLongUsage =
        "Usage:\n"
-       "    %s list-repos [options]\n"
+       "    %program% %command% [options]\n"
        "Lists all configured package repositories.\n"
-       "\n"
-;
+       "\n";
 
 
-static void
-print_command_usage_and_exit(bool error)
-{
-    fprintf(error ? stderr : stdout, kCommandUsage, kProgramName);
-    exit(error ? 1 : 0);
-}
+DEFINE_COMMAND(ListReposCommand, "list-repos", kShortUsage, kLongUsage)
 
 
 int
-command_list_repos(int argc, const char* const* argv)
+ListReposCommand::Execute(int argc, const char* const* argv)
 {
        bool verbose = false;
 
@@ -65,7 +64,7 @@ command_list_repos(int argc, const char* const* argv)
 
                switch (c) {
                        case 'h':
-                               print_command_usage_and_exit(false);
+                               PrintUsageAndExit(false);
                                break;
 
                        case 'v':
@@ -73,14 +72,14 @@ command_list_repos(int argc, const char* const* argv)
                                break;
 
                        default:
-                               print_command_usage_and_exit(true);
+                               PrintUsageAndExit(true);
                                break;
                }
        }
 
        // No remaining arguments.
        if (argc != optind)
-               print_command_usage_and_exit(true);
+               PrintUsageAndExit(true);
 
        BStringList repositoryNames(20);
        BPackageRoster roster;
diff --git a/src/bin/pkgman/command_refresh.cpp 
b/src/bin/pkgman/command_refresh.cpp
index 176f5d2..50764c9 100644
--- a/src/bin/pkgman/command_refresh.cpp
+++ b/src/bin/pkgman/command_refresh.cpp
@@ -15,6 +15,7 @@
 #include <package/RefreshRepositoryRequest.h>
 #include <package/PackageRoster.h>
 
+#include "Command.h"
 #include "DecisionProvider.h"
 #include "JobStateListener.h"
 #include "pkgman.h"
@@ -26,23 +27,22 @@ using namespace BPackageKit;
 // TODO: internationalization!
 
 
-static const char* kCommandUsage =
-       "Usage: %s refresh [<repo-name> ...]\n"
+static const char* const kShortUsage =
+       "  %command% [<repo-name> ...]\n"
+       "    Refreshes all or just the given repositories.\n";
+
+static const char* const kLongUsage =
+       "Usage: %program% %command% [<repo-name> ...]\n"
        "Refreshes all or just the given repositories.\n"
-       "\n"
-;
+       "\n";
 
 
-static void
-print_command_usage_and_exit(bool error)
-{
-    fprintf(error ? stderr : stdout, kCommandUsage, kProgramName);
-    exit(error ? 1 : 0);
-}
+DEFINE_COMMAND(RefreshCommand, "refresh", kShortUsage, kLongUsage)
+
 
 
 int
-command_refresh(int argc, const char* const* argv)
+RefreshCommand::Execute(int argc, const char* const* argv)
 {
        while (true) {
                static struct option sLongOptions[] = {
@@ -57,11 +57,11 @@ command_refresh(int argc, const char* const* argv)
 
                switch (c) {
                        case 'h':
-                               print_command_usage_and_exit(false);
+                               PrintUsageAndExit(false);
                                break;
 
                        default:
-                               print_command_usage_and_exit(true);
+                               PrintUsageAndExit(true);
                                break;
                }
        }
diff --git a/src/bin/pkgman/command_resolve_dependencies.cpp 
b/src/bin/pkgman/command_resolve_dependencies.cpp
index e585f6d..7388233 100644
--- a/src/bin/pkgman/command_resolve_dependencies.cpp
+++ b/src/bin/pkgman/command_resolve_dependencies.cpp
@@ -20,6 +20,7 @@
 
 #include <AutoDeleter.h>
 
+#include "Command.h"
 #include "pkgman.h"
 #include "RepositoryBuilder.h"
 
@@ -30,8 +31,12 @@
 using namespace BPackageKit;
 
 
-static const char* kCommandUsage =
-       "Usage: %s resolve-dependencies <package> <repository> [ <priority> ] 
...\n"
+static const char* const kShortUsage =
+       "  %command% <package> <repository> [ <priority> ] ...\n"
+       "    Resolves all packages a given package depends on.\n";
+
+static const char* const kLongUsage =
+       "Usage: %program% %command% <package> <repository> [ <priority> ] ...\n"
        "Resolves and lists all packages a given package depends on. Fails, 
if\n"
        "not all dependencies could be resolved.\n"
        "\n"
@@ -46,16 +51,11 @@ static const char* kCommandUsage =
        "  <priority>\n"
        "    Can follow a <repository> to specify the priority of that\n"
        "    repository. The default priority is 0.\n"
-       "\n"
-;
+       "\n";
 
 
-static void
-print_command_usage_and_exit(bool error)
-{
-    fprintf(error ? stderr : stdout, kCommandUsage, kProgramName);
-    exit(error ? 1 : 0);
-}
+DEFINE_COMMAND(ResolveDependenciesCommand, "resolve-dependencies", kShortUsage,
+       kLongUsage)
 
 
 static void
@@ -107,7 +107,7 @@ verify_result(const BSolverResult& result, BSolverPackage* 
specifiedPackage)
 
 
 int
-command_resolve_dependencies(int argc, const char* const* argv)
+ResolveDependenciesCommand::Execute(int argc, const char* const* argv)
 {
        while (true) {
                static struct option sLongOptions[] = {
@@ -122,11 +122,11 @@ command_resolve_dependencies(int argc, const char* const* 
argv)
 
                switch (c) {
                        case 'h':
-                               print_command_usage_and_exit(false);
+                               PrintUsageAndExit(false);
                                break;
 
                        default:
-                               print_command_usage_and_exit(true);
+                               PrintUsageAndExit(true);
                                break;
                }
        }
@@ -134,7 +134,7 @@ command_resolve_dependencies(int argc, const char* const* 
argv)
        // The remaining arguments are the package (info) file and the 
repository
        // directories (at least one), optionally with priorities.
        if (argc < optind + 2)
-               print_command_usage_and_exit(true);
+               PrintUsageAndExit(true);
 
        const char* packagePath = argv[optind++];
        int repositoryDirectoryCount = argc - optind;
diff --git a/src/bin/pkgman/command_search.cpp 
b/src/bin/pkgman/command_search.cpp
index 41334e2..f65db3e 100644
--- a/src/bin/pkgman/command_search.cpp
+++ b/src/bin/pkgman/command_search.cpp
@@ -19,6 +19,7 @@
 
 #include <AutoDeleter.h>
 
+#include "Command.h"
 #include "pkgman.h"
 #include "RepositoryBuilder.h"
 
@@ -34,8 +35,12 @@ using namespace BPackageKit;
 typedef std::map<BSolverPackage*, BString> PackagePathMap;
 
 
-static const char* kCommandUsage =
-       "Usage: %s search <search-string>\n"
+static const char* const kShortUsage =
+       "  %command% <search-string>\n"
+       "    Searches for packages matching <search-string>.\n";
+
+static const char* const kLongUsage =
+       "Usage: %program% %command% <search-string>\n"
        "Searches for packages matching <search-string>.\n"
        "\n"
        "Options:\n"
@@ -43,16 +48,10 @@ static const char* kCommandUsage =
        "    Only find installed packages.\n"
        "  -u, --uninstalled-only\n"
        "    Only find not installed packages.\n"
-       "\n"
-;
+       "\n";
 
 
-static void
-print_command_usage_and_exit(bool error)
-{
-    fprintf(error ? stderr : stdout, kCommandUsage, kProgramName);
-    exit(error ? 1 : 0);
-}
+DEFINE_COMMAND(SearchCommand, "search", kShortUsage, kLongUsage)
 
 
 static int
@@ -68,7 +67,7 @@ get_terminal_width()
 
 
 int
-command_search(int argc, const char* const* argv)
+SearchCommand::Execute(int argc, const char* const* argv)
 {
        bool installedOnly = false;
        bool uninstalledOnly = false;
@@ -88,7 +87,7 @@ command_search(int argc, const char* const* argv)
 
                switch (c) {
                        case 'h':
-                               print_command_usage_and_exit(false);
+                               PrintUsageAndExit(false);
                                break;
 
                        case 'i':
@@ -102,14 +101,14 @@ command_search(int argc, const char* const* argv)
                                break;
 
                        default:
-                               print_command_usage_and_exit(true);
+                               PrintUsageAndExit(true);
                                break;
                }
        }
 
        // The remaining argument is the search string.
        if (argc != optind + 1)
-               print_command_usage_and_exit(true);
+               PrintUsageAndExit(true);
 
        const char* searchString = argv[optind++];
 
diff --git a/src/bin/pkgman/pkgman.cpp b/src/bin/pkgman/pkgman.cpp
index 6611700..eddf6fb 100644
--- a/src/bin/pkgman/pkgman.cpp
+++ b/src/bin/pkgman/pkgman.cpp
@@ -11,34 +11,19 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "Command.h"
+
 
 extern const char* __progname;
 const char* kProgramName = __progname;
 
 
-static const char* kUsage =
+static const char* const kUsage =
        "Usage: %s <command> <command args>\n"
-       "Creates, inspects, or extracts a Haiku package.\n"
+       "Manages packages and package repository.\n"
        "\n"
        "Commands:\n"
-       "  add-repo <repo-base-url>\n"
-       "    Adds the repository with the given <repo-base-URL>.\n"
-       "\n"
-       "  drop-repo <repo-name>\n"
-       "    Drops the repository with the given <repo-name>.\n"
-       "\n"
-       "  list-repos\n"
-       "    Lists all repositories.\n"
-       "\n"
-       "  refresh [<repo-name> ...]\n"
-       "    Refreshes all or just the given repositories.\n"
-       "\n"
-       "  resolve-dependencies <package> <repository> [ <priority> ] ...\n"
-       "    Resolves all packages a given package depends on.\n"
-       "\n"
-       "  search <search-string>\n"
-       "    Searches for packages matching <search-string>.\n"
-       "\n"
+       "%s"
        "Common Options:\n"
        "  -h, --help   - Print this usage info.\n"
 ;
@@ -47,7 +32,14 @@ static const char* kUsage =
 void
 print_usage_and_exit(bool error)
 {
-    fprintf(error ? stderr : stdout, kUsage, kProgramName);
+       BString commandsUsage;
+       const CommandList& commands = CommandManager::Default()->Commands();
+       for (int32 i = 0; Command* command = commands.ItemAt(i); i++)
+               commandsUsage << command->ShortUsage() << '\n';
+
+    fprintf(error ? stderr : stdout, kUsage, kProgramName,
+       commandsUsage.String());
+
     exit(error ? 1 : 0);
 }
 
@@ -55,33 +47,19 @@ print_usage_and_exit(bool error)
 int
 main(int argc, const char* const* argv)
 {
+       CommandManager::Default()->InitCommands(kProgramName);
+
        if (argc < 2)
                print_usage_and_exit(true);
 
        const char* command = argv[1];
-       if (strncmp(command, "add-r", 5) == 0)
-               return command_add_repo(argc - 1, argv + 1);
-
-       if (strncmp(command, "drop-r", 6) == 0)
-               return command_drop_repo(argc - 1, argv + 1);
-
-       if (strncmp(command, "list-r", 6) == 0)
-               return command_list_repos(argc - 1, argv + 1);
-
-       if (strncmp(command, "refr", 4) == 0)
-               return command_refresh(argc - 1, argv + 1);
-
-       if (strcmp(command, "resolve-dependencies") == 0)
-               return command_resolve_dependencies(argc - 1, argv + 1);
-
-       if (strcmp(command, "search") == 0)
-               return command_search(argc - 1, argv + 1);
-
        if (strcmp(command, "help") == 0)
                print_usage_and_exit(false);
-       else
+
+       CommandList commands;
+       CommandManager::Default()->GetCommands(command, commands);
+       if (commands.CountItems() != 1)
                print_usage_and_exit(true);
 
-       // never gets here
-       return 0;
+       return commands.ItemAt(0)->Execute(argc - 1, argv + 1);
 }
diff --git a/src/bin/pkgman/pkgman.h b/src/bin/pkgman/pkgman.h
index c2a2fe9..eb30885 100644
--- a/src/bin/pkgman/pkgman.h
+++ b/src/bin/pkgman/pkgman.h
@@ -34,12 +34,6 @@ do {                                                         
                                                                \
 
 
 void   print_usage_and_exit(bool error);
-int            command_add_repo(int argc, const char* const* argv);
-int            command_drop_repo(int argc, const char* const* argv);
-int            command_list_repos(int argc, const char* const* argv);
-int            command_refresh(int argc, const char* const* argv);
-int            command_resolve_dependencies(int argc, const char* const* 
argv);  
-int            command_search(int argc, const char* const* argv);  
 
 
 #endif // PKGMAN_H


Other related posts: