1/*
2 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <PathFinder.h>
8
9#include <package/PackageResolvableExpression.h>
10#include <package/solver/SolverPackage.h>
11
12#include <directories.h>
13#include <package/manager/PackageManager.h>
14
15
16// NOTE: This is only the package kit specific part of BPathFinder. Everything
17// else is implemented in the storage kit.
18
19
20using namespace BPackageKit;
21using namespace BPackageKit::BPrivate;
22using namespace BPackageKit::BManager::BPrivate;
23
24
25static status_t
26find_package(const BPackageResolvableExpression& expression,
27	BString& _versionedPackageName)
28{
29	if (expression.InitCheck() != B_OK)
30		return B_BAD_VALUE;
31
32	// create the package manager -- we only want to use its solver
33	BPackageManager::ClientInstallationInterface installationInterface;
34	BPackageManager::UserInteractionHandler userInteractionHandler;
35	BPackageManager packageManager(B_PACKAGE_INSTALLATION_LOCATION_HOME,
36		&installationInterface, &userInteractionHandler);
37	packageManager.Init(BPackageManager::B_ADD_INSTALLED_REPOSITORIES);
38
39	// search
40	BObjectList<BSolverPackage> packages;
41	status_t error = packageManager.Solver()->FindPackages(expression.Name(),
42		BSolver::B_FIND_IN_NAME | BSolver::B_FIND_IN_PROVIDES, packages);
43	if (error != B_OK)
44		return B_ENTRY_NOT_FOUND;
45
46	// find the newest matching package
47	BSolverPackage* foundPackage = NULL;
48	for (int32 i = 0; BSolverPackage* package = packages.ItemAt(i); i++) {
49		if (package->Info().Matches(expression)
50			&& (foundPackage == NULL
51				|| package->Info().Version().Compare(
52					foundPackage->Info().Version()) > 0)) {
53			foundPackage = package;
54		}
55	}
56
57	if (foundPackage == NULL)
58		return B_ENTRY_NOT_FOUND;
59
60	BString version = foundPackage->Info().Version().ToString();
61	_versionedPackageName = foundPackage->VersionedName();
62	return _versionedPackageName.IsEmpty() ? B_NO_MEMORY : B_OK;
63}
64
65
66BPathFinder::BPathFinder(const BResolvableExpression& expression,
67	const char* dependency)
68{
69	SetTo(expression, dependency);
70}
71
72
73status_t
74BPathFinder::SetTo(const BResolvableExpression& expression,
75	const char* dependency)
76{
77	BString versionedPackageName;
78	fInitStatus = find_package(expression, versionedPackageName);
79	if (fInitStatus != B_OK)
80		return fInitStatus;
81
82	BString packageLinksPath;
83	packageLinksPath.SetToFormat(kSystemPackageLinksDirectory "/%s/.self",
84		versionedPackageName.String());
85	if (packageLinksPath.IsEmpty())
86		return fInitStatus = B_NO_MEMORY;
87
88	struct stat st;
89	if (lstat(packageLinksPath, &st) < 0)
90		return fInitStatus = B_ENTRY_NOT_FOUND;
91
92	return _SetTo(NULL, packageLinksPath, dependency);
93}
94