/* * Copyright 2013-2025, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Ingo Weinhold * Humdinger * Adrien Destugues */ #include #include #include #include #include "Command.h" #include "PackageManager.h" #include "pkgman.h" // TODO: internationalization! using namespace BPackageKit; using namespace BPackageKit::BPrivate; static const char* const kShortUsage = " %command% [--show ] [-v] \n" " Shows information for the specified package.\n"; static const char* const kLongUsage = "Usage: %program% %command% [--show ] [-v] \n" "\n" "Shows information for the specified package.\n" "\n" "The 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 .\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; // don't print errors 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; } } // The remaining argument, if any, is the package. const char* packageName = argv[optind++]; if (packageName == NULL) PrintUsageAndExit(true); if ((field != "header") && (field != "provides") && (field != "requires")) PrintUsageAndExit(true); // create the solver 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; // find packages BObjectList 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; } // select first exact match by package name 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") { // print out summary and description 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 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 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; }