diff --git a/src/bin/pkgman/Jamfile b/src/bin/pkgman/Jamfile index 4669d214f2..de3d08c07e 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 e099995bfc..f587451f32 100644 --- a/src/bin/pkgman/PackageManager.cpp +++ b/src/bin/pkgman/PackageManager.cpp @@ -193,6 +193,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() { @@ -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 7a8ebd050c..ca9b3a0c7e 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 PackageList; diff --git a/src/bin/pkgman/command_uninstall.cpp b/src/bin/pkgman/command_uninstall.cpp new file mode 100644 index 0000000000..5743603e73 --- /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 + */ + + +#include +#include +#include + +#include "Command.h" +#include "pkgman.h" +#include "PackageManager.h" + + +// TODO: internationalization! + + +using namespace BPackageKit; +using namespace BPackageKit::BPrivate; + + +static const char* const kShortUsage = + " %command% ...\n" + " Uninstalls one or more packages.\n"; + +static const char* const kLongUsage = + "Usage: %program% %command% ...\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; +}