xref: /haiku/src/kits/package/PathFinder.cpp (revision 71452e98334eaac603bf542d159e24788a46bebb)
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 
20 using namespace BPackageKit;
21 using namespace BPackageKit::BPrivate;
22 using namespace BPackageKit::BManager::BPrivate;
23 
24 
25 static status_t
26 find_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 
66 BPathFinder::BPathFinder(const BResolvableExpression& expression,
67 	const char* dependency)
68 {
69 	SetTo(expression, dependency);
70 }
71 
72 
73 status_t
74 BPathFinder::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