* Copyright 2013-2025, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <ingo_weinhold@gmx.de>
* Humdinger <humdingerb@gmail.com>
* Adrien Destugues <pulkomandy@pulkomandy.tk>
*/
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <package/solver/SolverPackage.h>
#include "Command.h"
#include "PackageManager.h"
#include "pkgman.h"
using namespace BPackageKit;
using namespace BPackageKit::BPrivate;
static const char* const kShortUsage =
" %command% [--show <field>] [-v] <package>\n"
" Shows information for the specified package.\n";
static const char* const kLongUsage =
"Usage: %program% %command% [--show <field>] [-v] <package>\n"
"\n"
"Shows information for the specified package.\n"
"\n"
"The <package> argument is the name by which the package\n"
"is looked up in a remote repository.\n"
"\n"
"Options:\n"
" -s, --show field\n"
" List a specific metadata field from the given <package>.\n"
" The available fields are:\n"
" * header: package name and description (this is the default)\n"
" * provides: entities provided by the given package\n"
" * requires: runtime dependencies of the given package\n"
" -v, --versions\n"
" Show version details for the provided/required entities.\n"
" Otherwise only their names are printed.\n"
;
DEFINE_COMMAND(InfoCommand, "info", kShortUsage, kLongUsage,
COMMAND_CATEGORY_PACKAGES)
int
InfoCommand::Execute(int argc, const char* const* argv)
{
bool versions = false;
BString field = "header";
while (true) {
static struct option sLongOptions[] = {
{ "debug", required_argument, 0, OPTION_DEBUG },
{ "help", no_argument, 0, 'h' },
{ "show", required_argument, 0, 's' },
{ "versions", no_argument, 0, 'v' },
{ 0, 0, 0, 0 }
};
opterr = 0;
int c = getopt_long(argc, (char**)argv, "hs:v", sLongOptions, NULL);
if (c == -1)
break;
if (fCommonOptions.HandleOption(c))
continue;
switch (c) {
case 'h':
PrintUsageAndExit(false);
break;
case 's':
field = optarg;
break;
case 'v':
versions = true;
break;
default:
PrintUsageAndExit(true);
break;
}
}
const char* packageName = argv[optind++];
if (packageName == NULL)
PrintUsageAndExit(true);
if ((field != "header") && (field != "provides") && (field != "requires"))
PrintUsageAndExit(true);
PackageManager packageManager(B_PACKAGE_INSTALLATION_LOCATION_SYSTEM);
packageManager.SetDebugLevel(fCommonOptions.DebugLevel());
packageManager.Init(
PackageManager::B_ADD_INSTALLED_REPOSITORIES
| PackageManager::B_ADD_REMOTE_REPOSITORIES);
uint32 flags = BSolver::B_FIND_CASE_INSENSITIVE | BSolver::B_FIND_IN_NAME;
BObjectList<BSolverPackage> packages;
status_t error = packageManager.Solver()->FindPackages(packageName,
flags, packages);
if (error != B_OK)
DIE(error, "searching packages failed");
if (packages.IsEmpty()) {
printf("No matching packages found.\n");
return 0;
}
int32 packageCount = packages.CountItems();
BSolverPackage* package = NULL;
for (int32 i = 0; i < packageCount; i++) {
if (packages.ItemAt(i)->Name() == packageName) {
package = packages.ItemAt(i);
break;
}
}
if (package == NULL) {
fprintf(stderr, "Could not find a package exactly named: \"%s\".\n", packageName);
return 1;
}
if (field == "header") {
BString text("%name%: %summary%\n\n%description%\n");
text.ReplaceFirst("%name%", package->Name());
text.ReplaceFirst("%summary%", package->Info().Summary());
text.ReplaceFirst("%description%", package->Info().Description());
printf("%s\n", text.String());
return 0;
}
if (field == "provides") {
BObjectList<BPackageResolvable, true> providesList = package->Info().ProvidesList();
for (int32 i = 0; i < providesList.CountItems(); i++) {
if (versions)
printf("%s\n", providesList.ItemAt(i)->ToString().String());
else
printf("%s\n", providesList.ItemAt(i)->Name().String());
}
}
if (field == "requires") {
BObjectList<BPackageResolvableExpression, true> requiresList
= package->Info().RequiresList();
for (int32 i = 0; i < requiresList.CountItems(); i++) {
if (versions)
printf("%s\n", requiresList.ItemAt(i)->ToString().String());
else
printf("%s\n", requiresList.ItemAt(i)->Name().String());
}
}
return 0;
}