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