1/*
2 * Copyright 2013-2023, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Ingo Weinhold <ingo_weinhold@gmx.de>
7 *		Humdinger <humdingerb@gmail.com>
8 */
9
10
11#include <getopt.h>
12#include <stdio.h>
13#include <stdlib.h>
14
15#include <package/solver/SolverPackage.h>
16
17#include "Command.h"
18#include "PackageManager.h"
19#include "pkgman.h"
20
21
22// TODO: internationalization!
23
24
25using namespace BPackageKit;
26using namespace BPackageKit::BPrivate;
27
28
29static const char* const kShortUsage =
30	"  %command% <package>\n"
31	"    Shows summary and description of the specified package.\n";
32
33static const char* const kLongUsage =
34	"Usage: %program% %command% <package>\n"
35	"Shows summary and description of the specified package.\n"
36	"The <package> argument is the name by which the package\n"
37	"is looked up in a remote repository.\n"
38	"\n";
39
40
41DEFINE_COMMAND(InfoCommand, "info", kShortUsage, kLongUsage,
42	COMMAND_CATEGORY_PACKAGES)
43
44
45int
46InfoCommand::Execute(int argc, const char* const* argv)
47{
48	while (true) {
49		static struct option sLongOptions[] = {
50			{ "debug", required_argument, 0, OPTION_DEBUG },
51			{ "help", no_argument, 0, 'h' },
52			{ 0, 0, 0, 0 }
53		};
54
55		opterr = 0; // don't print errors
56		int c = getopt_long(argc, (char**)argv, "h", sLongOptions, NULL);
57
58		if (c == -1)
59			break;
60
61		if (fCommonOptions.HandleOption(c))
62			continue;
63
64		switch (c) {
65			case 'h':
66				PrintUsageAndExit(false);
67				break;
68
69			default:
70				PrintUsageAndExit(true);
71				break;
72		}
73	}
74
75	// The remaining argument, if any, is the package.
76	const char* packageName = argv[optind++];
77	if (packageName == NULL)
78		PrintUsageAndExit(true);
79
80	// create the solver
81	PackageManager packageManager(B_PACKAGE_INSTALLATION_LOCATION_SYSTEM);
82	packageManager.SetDebugLevel(fCommonOptions.DebugLevel());
83	packageManager.Init(
84		PackageManager::B_ADD_INSTALLED_REPOSITORIES
85		| PackageManager::B_ADD_REMOTE_REPOSITORIES);
86
87	uint32 flags = BSolver::B_FIND_CASE_INSENSITIVE | BSolver::B_FIND_IN_NAME;
88
89	// find packages
90	BObjectList<BSolverPackage> packages;
91	status_t error = packageManager.Solver()->FindPackages(packageName,
92		flags, packages);
93	if (error != B_OK)
94		DIE(error, "searching packages failed");
95
96	if (packages.IsEmpty()) {
97		printf("No matching packages found.\n");
98		return 0;
99	}
100
101	// print out summary and description of first exactly matching package
102	int32 packageCount = packages.CountItems();
103	for (int32 i = 0; i < packageCount; i++) {
104		BSolverPackage* package = packages.ItemAt(i);
105		if (package->Name() == packageName) {
106			BString text("%name%: %summary%\n\n%description%\n");
107			text.ReplaceFirst("%name%", package->Name());
108			text.ReplaceFirst("%summary%", package->Info().Summary());
109			text.ReplaceFirst("%description%", package->Info().Description());
110			printf("%s\n", text.String());
111			break;
112		}
113	}
114
115	return 0;
116}
117