Flesh out the package kit solver API quite a bit more
* Reorganize things a bit:
- BSolver is now an abstract base class.
- A libsolv based implementation, LibsolvSolver, lives in a new
add-on, which is loaded lazily.
- Get rid of libpackage_solver. Save for LibsolvSolver everything
is moved to libpackage.
- This is a nicer solution for the cyclic dependency caused by
libsolv (libsolvext to be precise) using the package kit for
reading repositories and package files.
* Add a solver result data structure and and an accessor the solver.
* Add problem reporting support to the solver. There aren't data
structures for the problem solutions yet and support for selecting
solutions and re-solving is missing as well.
This commit is contained in:
@@ -101,6 +101,7 @@ PRIVATE_SYSTEM_LIBS =
|
|||||||
libfluidsynth.so
|
libfluidsynth.so
|
||||||
libilmimf.so
|
libilmimf.so
|
||||||
liblpsolve55.so
|
liblpsolve55.so
|
||||||
|
libpackage-add-on-libsolv.so
|
||||||
libroot-addon-icu.so
|
libroot-addon-icu.so
|
||||||
;
|
;
|
||||||
SYSTEM_SERVERS = app_server cddb_daemon debug_server input_server mail_daemon
|
SYSTEM_SERVERS = app_server cddb_daemon debug_server input_server mail_daemon
|
||||||
|
|||||||
@@ -13,30 +13,42 @@ namespace BPackageKit {
|
|||||||
|
|
||||||
|
|
||||||
class BSolverPackageSpecifierList;
|
class BSolverPackageSpecifierList;
|
||||||
|
class BSolverProblem;
|
||||||
class BSolverRepository;
|
class BSolverRepository;
|
||||||
|
class BSolverResult;
|
||||||
|
|
||||||
|
|
||||||
class BSolver {
|
class BSolver {
|
||||||
public:
|
public:
|
||||||
BSolver();
|
virtual ~BSolver();
|
||||||
~BSolver();
|
|
||||||
|
|
||||||
status_t Init();
|
static status_t Create(BSolver*& _solver);
|
||||||
|
|
||||||
status_t AddRepository(BSolverRepository* repository);
|
virtual status_t Init() = 0;
|
||||||
|
|
||||||
status_t Install(
|
virtual status_t AddRepository(
|
||||||
|
BSolverRepository* repository) = 0;
|
||||||
|
|
||||||
|
virtual status_t Install(
|
||||||
const BSolverPackageSpecifierList&
|
const BSolverPackageSpecifierList&
|
||||||
packages);
|
packages) = 0;
|
||||||
|
|
||||||
private:
|
bool HasProblems() const
|
||||||
class Implementation;
|
{ return CountProblems() > 0; }
|
||||||
|
virtual int32 CountProblems() const = 0;
|
||||||
|
virtual BSolverProblem* ProblemAt(int32 index) const = 0;
|
||||||
|
|
||||||
private:
|
virtual status_t GetResult(BSolverResult& _result) = 0;
|
||||||
Implementation* fImplementation;
|
|
||||||
|
protected:
|
||||||
|
BSolver();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// function exported by the libsolv based add-on
|
||||||
|
extern "C" BSolver* create_solver();
|
||||||
|
|
||||||
|
|
||||||
} // namespace BPackageKit
|
} // namespace BPackageKit
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _PACKAGE__SOLVER_PACKAGE_H_
|
||||||
|
#define _PACKAGE__SOLVER_PACKAGE_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <package/PackageInfo.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPackageKit {
|
||||||
|
|
||||||
|
|
||||||
|
class BSolverRepository;
|
||||||
|
|
||||||
|
|
||||||
|
class BSolverPackage {
|
||||||
|
public:
|
||||||
|
BSolverPackage(BSolverRepository* repository,
|
||||||
|
const BPackageInfo& packageInfo);
|
||||||
|
BSolverPackage(const BSolverPackage& other);
|
||||||
|
~BSolverPackage();
|
||||||
|
|
||||||
|
BSolverRepository* Repository() const;
|
||||||
|
const BPackageInfo& Info() const;
|
||||||
|
|
||||||
|
BString Name() const;
|
||||||
|
BString VersionedName() const;
|
||||||
|
|
||||||
|
BSolverPackage& operator=(const BSolverPackage& other);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BSolverRepository* fRepository;
|
||||||
|
BPackageInfo fInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace BPackageKit
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _PACKAGE__SOLVER_PACKAGE_H_
|
||||||
@@ -28,6 +28,7 @@ public:
|
|||||||
|
|
||||||
bool AppendSpecifier(
|
bool AppendSpecifier(
|
||||||
const BSolverPackageSpecifier& specifier);
|
const BSolverPackageSpecifier& specifier);
|
||||||
|
void MakeEmpty();
|
||||||
|
|
||||||
BSolverPackageSpecifierList& operator=(
|
BSolverPackageSpecifierList& operator=(
|
||||||
const BSolverPackageSpecifierList& other);
|
const BSolverPackageSpecifierList& other);
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _PACKAGE__SOLVER_PROBLEM_H_
|
||||||
|
#define _PACKAGE__SOLVER_PROBLEM_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <package/PackageResolvableExpression.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPackageKit {
|
||||||
|
|
||||||
|
|
||||||
|
class BSolverPackage;
|
||||||
|
|
||||||
|
|
||||||
|
class BSolverProblem {
|
||||||
|
public:
|
||||||
|
enum BType {
|
||||||
|
B_UNSPECIFIED,
|
||||||
|
B_NOT_IN_DISTUPGRADE_REPOSITORY,
|
||||||
|
B_INFERIOR_ARCHITECTURE,
|
||||||
|
B_INSTALLED_PACKAGE_PROBLEM,
|
||||||
|
B_CONFLICTING_REQUESTS,
|
||||||
|
B_REQUESTED_RESOLVABLE_NOT_PROVIDED,
|
||||||
|
B_REQUESTED_RESOLVABLE_PROVIDED_BY_SYSTEM,
|
||||||
|
B_DEPENDENCY_PROBLEM,
|
||||||
|
B_PACKAGE_NOT_INSTALLABLE,
|
||||||
|
B_DEPENDENCY_NOT_PROVIDED,
|
||||||
|
B_PACKAGE_NAME_CLASH,
|
||||||
|
B_PACKAGE_CONFLICT,
|
||||||
|
B_PACKAGE_OBSOLETES_RESOLVABLE,
|
||||||
|
B_INSTALLED_PACKAGE_OBSOLETES_RESOLVABLE,
|
||||||
|
B_PACKAGE_IMPLICITLY_OBSOLETES_RESOLVABLE,
|
||||||
|
B_DEPENDENCY_NOT_INSTALLABLE,
|
||||||
|
B_SELF_CONFLICT
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
BSolverProblem(BType type,
|
||||||
|
BSolverPackage* sourcePackage,
|
||||||
|
BSolverPackage* targetPackage = NULL);
|
||||||
|
BSolverProblem(BType type,
|
||||||
|
BSolverPackage* sourcePackage,
|
||||||
|
BSolverPackage* targetPackage,
|
||||||
|
const BPackageResolvableExpression&
|
||||||
|
dependency);
|
||||||
|
~BSolverProblem();
|
||||||
|
|
||||||
|
BType Type() const;
|
||||||
|
BSolverPackage* SourcePackage() const;
|
||||||
|
BSolverPackage* TargetPackage() const;
|
||||||
|
const BPackageResolvableExpression& Dependency() const;
|
||||||
|
|
||||||
|
BString ToString() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
BType fType;
|
||||||
|
BSolverPackage* fSourcePackage;
|
||||||
|
BSolverPackage* fTargetPackage;
|
||||||
|
BPackageResolvableExpression fDependency;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace BPackageKit
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _PACKAGE__SOLVER_PROBLEM_H_
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#define _PACKAGE__SOLVER_REPOSITORY_H_
|
#define _PACKAGE__SOLVER_REPOSITORY_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ObjectList.h>
|
||||||
#include <package/PackageDefs.h>
|
#include <package/PackageDefs.h>
|
||||||
#include <package/PackageInfoSet.h>
|
#include <package/PackageInfoSet.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
@@ -16,6 +17,7 @@ namespace BPackageKit {
|
|||||||
|
|
||||||
class BPackageInfo;
|
class BPackageInfo;
|
||||||
class BRepositoryConfig;
|
class BRepositoryConfig;
|
||||||
|
class BSolverPackage;
|
||||||
|
|
||||||
|
|
||||||
class BSolverRepository {
|
class BSolverRepository {
|
||||||
@@ -45,21 +47,27 @@ public:
|
|||||||
status_t InitCheck();
|
status_t InitCheck();
|
||||||
|
|
||||||
bool IsInstalled() const;
|
bool IsInstalled() const;
|
||||||
|
void SetInstalled(bool isInstalled);
|
||||||
|
|
||||||
BString Name() const;
|
BString Name() const;
|
||||||
uint8 Priority() const;
|
uint8 Priority() const;
|
||||||
|
|
||||||
|
bool IsEmpty() const;
|
||||||
|
int32 CountPackages() const;
|
||||||
|
BSolverPackage* PackageAt(int32 index) const;
|
||||||
|
|
||||||
status_t AddPackage(const BPackageInfo& info);
|
status_t AddPackage(const BPackageInfo& info);
|
||||||
status_t AddPackages(
|
status_t AddPackages(
|
||||||
BPackageInstallationLocation location);
|
BPackageInstallationLocation location);
|
||||||
|
|
||||||
Iterator GetIterator() const;
|
private:
|
||||||
|
typedef BObjectList<BSolverPackage> PackageList;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BString fName;
|
BString fName;
|
||||||
uint8 fPriority;
|
uint8 fPriority;
|
||||||
bool fIsInstalled;
|
bool fIsInstalled;
|
||||||
BPackageInfoSet fPackages;
|
PackageList fPackages;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _PACKAGE__SOLVER_RESULT_H_
|
||||||
|
#define _PACKAGE__SOLVER_RESULT_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <ObjectList.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPackageKit {
|
||||||
|
|
||||||
|
|
||||||
|
class BSolverPackage;
|
||||||
|
|
||||||
|
|
||||||
|
class BSolverResultElement {
|
||||||
|
public:
|
||||||
|
enum BType {
|
||||||
|
B_TYPE_INSTALL,
|
||||||
|
B_TYPE_UNINSTALL
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
BSolverResultElement(BType type,
|
||||||
|
BSolverPackage* package);
|
||||||
|
BSolverResultElement(
|
||||||
|
const BSolverResultElement& other);
|
||||||
|
~BSolverResultElement();
|
||||||
|
|
||||||
|
BType Type() const;
|
||||||
|
BSolverPackage* Package() const;
|
||||||
|
|
||||||
|
BSolverResultElement& operator=(const BSolverResultElement& other);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BType fType;
|
||||||
|
BSolverPackage* fPackage;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class BSolverResult {
|
||||||
|
public:
|
||||||
|
BSolverResult();
|
||||||
|
~BSolverResult();
|
||||||
|
|
||||||
|
bool IsEmpty() const;
|
||||||
|
int32 CountElements() const;
|
||||||
|
const BSolverResultElement* ElementAt(int32 index) const;
|
||||||
|
|
||||||
|
void MakeEmpty();
|
||||||
|
bool AppendElement(
|
||||||
|
const BSolverResultElement& element);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef BObjectList<BSolverResultElement> ElementList;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ElementList fElements;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace BPackageKit
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _PACKAGE__SOLVER_RESULT_H_
|
||||||
@@ -7,6 +7,7 @@ UsePrivateHeaders
|
|||||||
shared ;
|
shared ;
|
||||||
|
|
||||||
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits package hpkg ] ;
|
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits package hpkg ] ;
|
||||||
|
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits package solver ] ;
|
||||||
|
|
||||||
HPKG_SOURCES =
|
HPKG_SOURCES =
|
||||||
AttributeDataReader.cpp
|
AttributeDataReader.cpp
|
||||||
@@ -76,6 +77,14 @@ SharedLibrary libpackage.so
|
|||||||
NoErrorOutput.cpp
|
NoErrorOutput.cpp
|
||||||
StandardErrorOutput.cpp
|
StandardErrorOutput.cpp
|
||||||
|
|
||||||
|
# solver
|
||||||
|
Solver.cpp
|
||||||
|
SolverPackage.cpp
|
||||||
|
SolverPackageSpecifier.cpp
|
||||||
|
SolverPackageSpecifierList.cpp
|
||||||
|
SolverProblem.cpp
|
||||||
|
SolverRepository.cpp
|
||||||
|
SolverResult.cpp
|
||||||
:
|
:
|
||||||
libshared.a be z $(TARGET_LIBSTDC++)
|
libshared.a be z $(TARGET_LIBSTDC++)
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
SubDir HAIKU_TOP src kits package solver ;
|
SubDir HAIKU_TOP src kits package solver ;
|
||||||
|
|
||||||
UsePrivateHeaders shared ;
|
# add-on implementing a libsolv based BSolver
|
||||||
|
|
||||||
# TODO: Add properly to BuildFeatures and remove here!
|
|
||||||
HAIKU_LIBSOLV_INSTALL_DIR ?= /Transfer/ports/libsolv-install/boot/common ;
|
|
||||||
HAIKU_LIBSOLV_HEADERS ?= $(HAIKU_LIBSOLV_INSTALL_DIR)/include ;
|
|
||||||
HAIKU_LIBSOLV_LIBS ?= $(HAIKU_LIBSOLV_INSTALL_DIR)/lib/libsolv.so
|
|
||||||
$(HAIKU_LIBSOLV_INSTALL_DIR)/lib/libsolvext.so ;
|
|
||||||
|
|
||||||
SubDirSysHdrs $(HAIKU_LIBSOLV_HEADERS) ;
|
SubDirSysHdrs $(HAIKU_LIBSOLV_HEADERS) ;
|
||||||
SubDirHdrs $(HAIKU_LIBSOLV_HEADERS)/solv ;
|
SubDirHdrs $(HAIKU_LIBSOLV_HEADERS)/solv ;
|
||||||
|
|
||||||
|
UsePrivateHeaders shared ;
|
||||||
|
|
||||||
SharedLibrary libpackage_solver.so
|
|
||||||
|
SharedLibrary libpackage-add-on-libsolv.so
|
||||||
:
|
:
|
||||||
Solver.cpp
|
LibsolvSolver.cpp
|
||||||
SolverPackageSpecifier.cpp
|
|
||||||
SolverPackageSpecifierList.cpp
|
|
||||||
SolverRepository.cpp
|
|
||||||
:
|
:
|
||||||
package $(HAIKU_LIBSOLV_LIBS) be $(TARGET_LIBSTDC++)
|
package $(HAIKU_LIBSOLV_LIBS) be $(TARGET_LIBSTDC++)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
Includes [ FGristFiles LibsolvSolver.cpp ]
|
||||||
|
: $(HAIKU_LIBSOLV_HEADERS_DEPENDENCY) ;
|
||||||
|
|||||||
@@ -0,0 +1,619 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ingo Weinhold <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "LibsolvSolver.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <solv/poolarch.h>
|
||||||
|
#include <solv/repo.h>
|
||||||
|
#include <solv/repo_haiku.h>
|
||||||
|
#include <solv/selection.h>
|
||||||
|
#include <solv/solverdebug.h>
|
||||||
|
|
||||||
|
#include <package/PackageResolvableExpression.h>
|
||||||
|
#include <package/RepositoryCache.h>
|
||||||
|
#include <package/solver/SolverPackage.h>
|
||||||
|
#include <package/solver/SolverPackageSpecifier.h>
|
||||||
|
#include <package/solver/SolverPackageSpecifierList.h>
|
||||||
|
#include <package/solver/SolverProblem.h>
|
||||||
|
#include <package/solver/SolverRepository.h>
|
||||||
|
#include <package/solver/SolverResult.h>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
#include <ObjectList.h>
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: libsolv doesn't have any helpful out-of-memory handling. It just just
|
||||||
|
// abort()s. Obviously that isn't good behavior for a library.
|
||||||
|
|
||||||
|
|
||||||
|
BSolver*
|
||||||
|
BPackageKit::create_solver()
|
||||||
|
{
|
||||||
|
return new(std::nothrow) LibsolvSolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct LibsolvSolver::SolvQueue : Queue {
|
||||||
|
SolvQueue()
|
||||||
|
{
|
||||||
|
queue_init(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~SolvQueue()
|
||||||
|
{
|
||||||
|
queue_free(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct LibsolvSolver::RepositoryInfo {
|
||||||
|
RepositoryInfo(BSolverRepository* repository)
|
||||||
|
:
|
||||||
|
fRepository(repository),
|
||||||
|
fSolvRepo(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BSolverRepository* Repository() const
|
||||||
|
{
|
||||||
|
return fRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
Repo* SolvRepo()
|
||||||
|
{
|
||||||
|
return fSolvRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSolvRepo(Repo* repo)
|
||||||
|
{
|
||||||
|
fSolvRepo = repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
BSolverRepository* fRepository;
|
||||||
|
Repo* fSolvRepo;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - LibsolvSolver
|
||||||
|
|
||||||
|
|
||||||
|
LibsolvSolver::LibsolvSolver()
|
||||||
|
:
|
||||||
|
fPool(NULL),
|
||||||
|
fSolver(NULL),
|
||||||
|
fRepositoryInfos(10, true),
|
||||||
|
fInstalledRepository(NULL),
|
||||||
|
fProblems(10, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LibsolvSolver::~LibsolvSolver()
|
||||||
|
{
|
||||||
|
_Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
LibsolvSolver::Init()
|
||||||
|
{
|
||||||
|
_Cleanup();
|
||||||
|
|
||||||
|
fPool = pool_create();
|
||||||
|
|
||||||
|
// Set the system architecture. We use what uname() returns unless we're on
|
||||||
|
// x86 gcc2.
|
||||||
|
{
|
||||||
|
const char* arch;
|
||||||
|
#ifdef __HAIKU_ARCH_X86
|
||||||
|
#if (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_2
|
||||||
|
arch = "x86_gcc2";
|
||||||
|
#else
|
||||||
|
arch = "x86";
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
struct utsname info;
|
||||||
|
if (uname(&info) != 0)
|
||||||
|
return errno;
|
||||||
|
arch = info.machine;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pool_setarchpolicy(fPool, arch);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
LibsolvSolver::AddRepository(BSolverRepository* repository)
|
||||||
|
{
|
||||||
|
if (repository == NULL || repository->InitCheck() != B_OK)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// If the repository represents installed packages, check, if we already
|
||||||
|
// have such a repository.
|
||||||
|
if (repository->IsInstalled() && fInstalledRepository != NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// add the repository info
|
||||||
|
RepositoryInfo* info = new(std::nothrow) RepositoryInfo(repository);
|
||||||
|
if (info == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
if (!fRepositoryInfos.AddItem(info)) {
|
||||||
|
delete info;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (repository->IsInstalled())
|
||||||
|
fInstalledRepository = info;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
LibsolvSolver::Install(const BSolverPackageSpecifierList& packages)
|
||||||
|
{
|
||||||
|
if (packages.IsEmpty())
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// TODO: Clean up first?
|
||||||
|
|
||||||
|
// add repositories to pool
|
||||||
|
status_t error = _AddRepositories();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// prepare pool for solving
|
||||||
|
pool_createwhatprovides(fPool);
|
||||||
|
|
||||||
|
// add the packages to install to the job queue
|
||||||
|
SolvQueue jobs;
|
||||||
|
|
||||||
|
int32 packageCount = packages.CountSpecifiers();
|
||||||
|
for (int32 i = 0; i < packageCount; i++) {
|
||||||
|
const BSolverPackageSpecifier& specifier = *packages.SpecifierAt(i);
|
||||||
|
|
||||||
|
// find matching packages
|
||||||
|
SolvQueue matchingPackages;
|
||||||
|
|
||||||
|
int flags = SELECTION_NAME | SELECTION_PROVIDES | SELECTION_GLOB
|
||||||
|
| SELECTION_CANON | SELECTION_DOTARCH | SELECTION_REL;
|
||||||
|
// TODO: All flags needed/useful?
|
||||||
|
/*int matchFlags =*/ selection_make(fPool, &matchingPackages,
|
||||||
|
specifier.Expression().Name(), flags);
|
||||||
|
// TODO: Don't just match the name, but also the version, if given!
|
||||||
|
if (matchingPackages.count == 0)
|
||||||
|
return B_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
// restrict to the matching repository
|
||||||
|
if (BSolverRepository* repository = specifier.Repository()) {
|
||||||
|
RepositoryInfo* repositoryInfo = _GetRepositoryInfo(repository);
|
||||||
|
if (repositoryInfo == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
SolvQueue repoFilter;
|
||||||
|
queue_push2(&repoFilter,
|
||||||
|
SOLVER_SOLVABLE_REPO/* | SOLVER_SETREPO | SOLVER_SETVENDOR*/,
|
||||||
|
repositoryInfo->SolvRepo()->repoid);
|
||||||
|
|
||||||
|
selection_filter(fPool, &matchingPackages, &repoFilter);
|
||||||
|
|
||||||
|
if (matchingPackages.count == 0)
|
||||||
|
return B_NAME_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < matchingPackages.count; j++)
|
||||||
|
queue_push(&jobs, matchingPackages.elements[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add solver mode to job queue elements
|
||||||
|
int solverMode = SOLVER_INSTALL;
|
||||||
|
for (int i = 0; i < jobs.count; i += 2) {
|
||||||
|
jobs.elements[i] |= solverMode;
|
||||||
|
// if (cleandeps)
|
||||||
|
// jobs.elements[i] |= SOLVER_CLEANDEPS;
|
||||||
|
// if (forcebest)
|
||||||
|
// jobs.elements[i] |= SOLVER_FORCEBEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the solver and solve
|
||||||
|
fSolver = solver_create(fPool);
|
||||||
|
solver_set_flag(fSolver, SOLVER_FLAG_SPLITPROVIDES, 1);
|
||||||
|
solver_set_flag(fSolver, SOLVER_FLAG_BEST_OBEY_POLICY, 1);
|
||||||
|
|
||||||
|
// get the problems (if any)
|
||||||
|
fProblems.MakeEmpty();
|
||||||
|
|
||||||
|
int problemCount = solver_solve(fSolver, &jobs);
|
||||||
|
for (Id problemId = 1; problemId <= problemCount; problemId++) {
|
||||||
|
error = _AddProblem(problemId);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
LibsolvSolver::CountProblems() const
|
||||||
|
{
|
||||||
|
return fProblems.CountItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverProblem*
|
||||||
|
LibsolvSolver::ProblemAt(int32 index) const
|
||||||
|
{
|
||||||
|
return fProblems.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
LibsolvSolver::GetResult(BSolverResult& _result)
|
||||||
|
{
|
||||||
|
if (HasProblems())
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
_result.MakeEmpty();
|
||||||
|
|
||||||
|
Transaction* transaction = solver_create_transaction(fSolver);
|
||||||
|
CObjectDeleter<Transaction> transactionDeleter(transaction,
|
||||||
|
&transaction_free);
|
||||||
|
|
||||||
|
if (transaction->steps.count == 0)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
// Get the packages that end up in the installation. The result queue
|
||||||
|
// contains newPackageCount new packages to install first, followed by the
|
||||||
|
// kept packages.
|
||||||
|
SolvQueue installedPackages;
|
||||||
|
int newPackageCount = transaction_installedresult(transaction,
|
||||||
|
&installedPackages);
|
||||||
|
|
||||||
|
transaction_order(transaction, 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < transaction->steps.count; i++) {
|
||||||
|
Id solvableId = transaction->steps.elements[i];
|
||||||
|
Solvable* solvable = pool_id2solvable(fPool, solvableId);
|
||||||
|
switch (transaction_type(transaction, solvableId,
|
||||||
|
SOLVER_TRANSACTION_RPM_ONLY)) {
|
||||||
|
case SOLVER_TRANSACTION_ERASE:
|
||||||
|
{
|
||||||
|
BSolverPackage* package = _GetPackage(solvable);
|
||||||
|
if (package == NULL)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
status_t error = _result.AppendElement(
|
||||||
|
BSolverResultElement(BSolverResultElement::B_TYPE_UNINSTALL,
|
||||||
|
package));
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SOLVER_TRANSACTION_INSTALL:
|
||||||
|
case SOLVER_TRANSACTION_MULTIINSTALL:
|
||||||
|
{
|
||||||
|
// check, if it really is a new package
|
||||||
|
// TODO: Is this check really necessary?
|
||||||
|
bool foundPackage = false;
|
||||||
|
for (int j = 0; j < newPackageCount; j++) {
|
||||||
|
if (installedPackages.elements[j] == solvableId) {
|
||||||
|
foundPackage = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundPackage)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BSolverPackage* package = _GetPackage(solvable);
|
||||||
|
if (package == NULL)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
if (!_result.AppendElement(
|
||||||
|
BSolverResultElement(
|
||||||
|
BSolverResultElement::B_TYPE_INSTALL, package))) {
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LibsolvSolver::_Cleanup()
|
||||||
|
{
|
||||||
|
fProblems.MakeEmpty();
|
||||||
|
fSolvablePackages.clear();
|
||||||
|
fInstalledRepository = NULL;
|
||||||
|
fRepositoryInfos.MakeEmpty();
|
||||||
|
|
||||||
|
if (fSolver != NULL) {
|
||||||
|
solver_free(fSolver);
|
||||||
|
fSolver = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fPool != NULL) {
|
||||||
|
pool_free(fPool);
|
||||||
|
fPool = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
LibsolvSolver::_AddRepositories()
|
||||||
|
{
|
||||||
|
int32 repositoryCount = fRepositoryInfos.CountItems();
|
||||||
|
for (int32 i = 0; i < repositoryCount; i++) {
|
||||||
|
RepositoryInfo* repositoryInfo = fRepositoryInfos.ItemAt(i);
|
||||||
|
BSolverRepository* repository = repositoryInfo->Repository();
|
||||||
|
Repo* repo = repo_create(fPool, repository->Name());
|
||||||
|
repositoryInfo->SetSolvRepo(repo);
|
||||||
|
|
||||||
|
repo->priority = 256 - repository->Priority();
|
||||||
|
repo->appdata = (void*)repositoryInfo;
|
||||||
|
|
||||||
|
int32 packageCount = repository->CountPackages();
|
||||||
|
for (int32 k = 0; k < packageCount; k++) {
|
||||||
|
BSolverPackage* package = repository->PackageAt(k);
|
||||||
|
Id solvableId = repo_add_haiku_package_info(repo, package->Info(),
|
||||||
|
REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE);
|
||||||
|
Solvable* solvable = pool_id2solvable(fPool, solvableId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
fSolvablePackages[solvable] = package;
|
||||||
|
} catch (std::bad_alloc&) {
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repo_internalize(repo);
|
||||||
|
|
||||||
|
if (repository->IsInstalled())
|
||||||
|
pool_set_installed(fPool, repo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LibsolvSolver::RepositoryInfo*
|
||||||
|
LibsolvSolver::_GetRepositoryInfo(BSolverRepository* repository) const
|
||||||
|
{
|
||||||
|
int32 repositoryCount = fRepositoryInfos.CountItems();
|
||||||
|
for (int32 i = 0; i < repositoryCount; i++) {
|
||||||
|
RepositoryInfo* repositoryInfo = fRepositoryInfos.ItemAt(i);
|
||||||
|
if (repository == repositoryInfo->Repository())
|
||||||
|
return repositoryInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverPackage*
|
||||||
|
LibsolvSolver::_GetPackage(Solvable* solvable) const
|
||||||
|
{
|
||||||
|
SolvableMap::const_iterator it = fSolvablePackages.find(solvable);
|
||||||
|
return it != fSolvablePackages.end() ? it->second : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverPackage*
|
||||||
|
LibsolvSolver::_GetPackage(Id solvableId) const
|
||||||
|
{
|
||||||
|
Solvable* solvable = pool_id2solvable(fPool, solvableId);
|
||||||
|
return solvable != NULL ? _GetPackage(solvable) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
LibsolvSolver::_AddProblem(Id problemId)
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
NEED_SOURCE = 0x1,
|
||||||
|
NEED_TARGET = 0x2,
|
||||||
|
NEED_DEPENDENCY = 0x4
|
||||||
|
};
|
||||||
|
|
||||||
|
Id ruleId = solver_findproblemrule(fSolver, problemId);
|
||||||
|
Id sourceId;
|
||||||
|
Id targetId;
|
||||||
|
Id dependencyId;
|
||||||
|
BSolverProblem::BType problemType = BSolverProblem::B_UNSPECIFIED;
|
||||||
|
uint32 needed = 0;
|
||||||
|
|
||||||
|
switch (solver_ruleinfo(fSolver, ruleId, &sourceId, &targetId,
|
||||||
|
&dependencyId)) {
|
||||||
|
case SOLVER_RULE_DISTUPGRADE:
|
||||||
|
problemType = BSolverProblem::B_NOT_IN_DISTUPGRADE_REPOSITORY;
|
||||||
|
needed = NEED_SOURCE;
|
||||||
|
break;
|
||||||
|
case SOLVER_RULE_INFARCH:
|
||||||
|
problemType = BSolverProblem::B_INFERIOR_ARCHITECTURE;
|
||||||
|
needed = NEED_SOURCE;
|
||||||
|
break;
|
||||||
|
case SOLVER_RULE_UPDATE:
|
||||||
|
problemType = BSolverProblem::B_INSTALLED_PACKAGE_PROBLEM;
|
||||||
|
needed = NEED_SOURCE;
|
||||||
|
break;
|
||||||
|
case SOLVER_RULE_JOB:
|
||||||
|
problemType = BSolverProblem::B_CONFLICTING_REQUESTS;
|
||||||
|
break;
|
||||||
|
case SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP:
|
||||||
|
problemType = BSolverProblem::B_REQUESTED_RESOLVABLE_NOT_PROVIDED;
|
||||||
|
needed = NEED_DEPENDENCY;
|
||||||
|
break;
|
||||||
|
case SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM:
|
||||||
|
problemType
|
||||||
|
= BSolverProblem::B_REQUESTED_RESOLVABLE_PROVIDED_BY_SYSTEM;
|
||||||
|
needed = NEED_DEPENDENCY;
|
||||||
|
break;
|
||||||
|
case SOLVER_RULE_RPM:
|
||||||
|
problemType = BSolverProblem::B_DEPENDENCY_PROBLEM;
|
||||||
|
break;
|
||||||
|
case SOLVER_RULE_RPM_NOT_INSTALLABLE:
|
||||||
|
problemType = BSolverProblem::B_PACKAGE_NOT_INSTALLABLE;
|
||||||
|
needed = NEED_SOURCE;
|
||||||
|
break;
|
||||||
|
case SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP:
|
||||||
|
problemType = BSolverProblem::B_DEPENDENCY_NOT_PROVIDED;
|
||||||
|
needed = NEED_SOURCE | NEED_DEPENDENCY;
|
||||||
|
break;
|
||||||
|
case SOLVER_RULE_RPM_SAME_NAME:
|
||||||
|
problemType = BSolverProblem::B_PACKAGE_NAME_CLASH;
|
||||||
|
needed = NEED_SOURCE | NEED_TARGET;
|
||||||
|
break;
|
||||||
|
case SOLVER_RULE_RPM_PACKAGE_CONFLICT:
|
||||||
|
problemType = BSolverProblem::B_PACKAGE_CONFLICT;
|
||||||
|
needed = NEED_SOURCE | NEED_TARGET | NEED_DEPENDENCY;
|
||||||
|
break;
|
||||||
|
case SOLVER_RULE_RPM_PACKAGE_OBSOLETES:
|
||||||
|
problemType = BSolverProblem::B_PACKAGE_OBSOLETES_RESOLVABLE;
|
||||||
|
needed = NEED_SOURCE | NEED_TARGET | NEED_DEPENDENCY;
|
||||||
|
break;
|
||||||
|
case SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES:
|
||||||
|
problemType
|
||||||
|
= BSolverProblem::B_INSTALLED_PACKAGE_OBSOLETES_RESOLVABLE;
|
||||||
|
needed = NEED_SOURCE | NEED_TARGET | NEED_DEPENDENCY;
|
||||||
|
break;
|
||||||
|
case SOLVER_RULE_RPM_IMPLICIT_OBSOLETES:
|
||||||
|
problemType
|
||||||
|
= BSolverProblem::B_PACKAGE_IMPLICITLY_OBSOLETES_RESOLVABLE;
|
||||||
|
needed = NEED_SOURCE | NEED_TARGET | NEED_DEPENDENCY;
|
||||||
|
break;
|
||||||
|
case SOLVER_RULE_RPM_PACKAGE_REQUIRES:
|
||||||
|
problemType = BSolverProblem::B_DEPENDENCY_NOT_INSTALLABLE;
|
||||||
|
needed = NEED_SOURCE | NEED_DEPENDENCY;
|
||||||
|
break;
|
||||||
|
case SOLVER_RULE_RPM_SELF_CONFLICT:
|
||||||
|
problemType = BSolverProblem::B_SELF_CONFLICT;
|
||||||
|
needed = NEED_SOURCE | NEED_DEPENDENCY;
|
||||||
|
break;
|
||||||
|
case SOLVER_RULE_UNKNOWN:
|
||||||
|
case SOLVER_RULE_FEATURE:
|
||||||
|
case SOLVER_RULE_LEARNT:
|
||||||
|
case SOLVER_RULE_CHOICE:
|
||||||
|
case SOLVER_RULE_BEST:
|
||||||
|
problemType = BSolverProblem::B_UNSPECIFIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
BSolverPackage* sourcePackage = NULL;
|
||||||
|
if ((needed & NEED_SOURCE) != 0) {
|
||||||
|
sourcePackage = _GetPackage(sourceId);
|
||||||
|
if (sourcePackage == NULL)
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
BSolverPackage* targetPackage = NULL;
|
||||||
|
if ((needed & NEED_TARGET) != 0) {
|
||||||
|
targetPackage = _GetPackage(targetId);
|
||||||
|
if (targetPackage == NULL)
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
BPackageResolvableExpression dependency;
|
||||||
|
if ((needed & NEED_DEPENDENCY) != 0) {
|
||||||
|
status_t error = _GetResolvableExpression(dependencyId, dependency);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
BSolverProblem* problem = new(std::nothrow) BSolverProblem(problemType,
|
||||||
|
sourcePackage, targetPackage, dependency);
|
||||||
|
if (problem == NULL || !fProblems.AddItem(problem)) {
|
||||||
|
delete problem;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
LibsolvSolver::_GetResolvableExpression(Id id,
|
||||||
|
BPackageResolvableExpression& _expression) const
|
||||||
|
{
|
||||||
|
// Try to translate the libsolv ID to a resolvable expression. Generally
|
||||||
|
// that doesn't work, since libsolv is more expressive, but all the stuff
|
||||||
|
// we feed libsolv we should be able to translate back.
|
||||||
|
|
||||||
|
if (!ISRELDEP(id)) {
|
||||||
|
// just a string
|
||||||
|
_expression.SetTo(pool_id2str(fPool, id));
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// a composite -- analyze it
|
||||||
|
Reldep* reldep = GETRELDEP(fPool, id);
|
||||||
|
|
||||||
|
// No support for more than one level, so both name and evr must be strings.
|
||||||
|
if (ISRELDEP(reldep->name) || ISRELDEP(reldep->evr))
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
const char* name = pool_id2str(fPool, reldep->name);
|
||||||
|
const char* versionString = pool_id2str(fPool, reldep->evr);
|
||||||
|
if (name == NULL || versionString == NULL)
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
// get the operator -- we don't support all libsolv supports
|
||||||
|
BPackageResolvableOperator op;
|
||||||
|
switch (reldep->flags) {
|
||||||
|
case 1:
|
||||||
|
op = B_PACKAGE_RESOLVABLE_OP_GREATER;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
op = B_PACKAGE_RESOLVABLE_OP_EQUAL;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
op = B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
op = B_PACKAGE_RESOLVABLE_OP_LESS;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
op = B_PACKAGE_RESOLVABLE_OP_NOT_EQUAL;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
op = B_PACKAGE_RESOLVABLE_OP_LESS_EQUAL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the version (cut off the empty epoch)
|
||||||
|
if (versionString[0] == ':')
|
||||||
|
versionString++;
|
||||||
|
|
||||||
|
BPackageVersion version;
|
||||||
|
status_t error = version.SetTo(versionString, true);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error == B_BAD_DATA ? B_NOT_SUPPORTED : error;
|
||||||
|
|
||||||
|
_expression.SetTo(name, op, version);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef HAIKU_LIBSOLV_SOLVER_H
|
||||||
|
#define HAIKU_LIBSOLV_SOLVER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <ObjectList.h>
|
||||||
|
#include <package/solver/Solver.h>
|
||||||
|
|
||||||
|
#include <solv/pool.h>
|
||||||
|
#include <solv/solver.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace BPackageKit;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPackageKit {
|
||||||
|
class BPackageResolvableExpression;
|
||||||
|
class BSolverPackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class LibsolvSolver : public BSolver {
|
||||||
|
public:
|
||||||
|
LibsolvSolver();
|
||||||
|
virtual ~LibsolvSolver();
|
||||||
|
|
||||||
|
virtual status_t Init();
|
||||||
|
|
||||||
|
virtual status_t AddRepository(BSolverRepository* repository);
|
||||||
|
|
||||||
|
virtual status_t Install(
|
||||||
|
const BSolverPackageSpecifierList&
|
||||||
|
packages);
|
||||||
|
|
||||||
|
virtual int32 CountProblems() const;
|
||||||
|
virtual BSolverProblem* ProblemAt(int32 index) const;
|
||||||
|
|
||||||
|
virtual status_t GetResult(BSolverResult& _result);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct SolvQueue;
|
||||||
|
struct RepositoryInfo;
|
||||||
|
|
||||||
|
typedef BObjectList<RepositoryInfo> RepositoryInfoList;
|
||||||
|
typedef BObjectList<BSolverProblem> ProblemList;
|
||||||
|
typedef std::map<Solvable*, BSolverPackage*> SolvableMap;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _Cleanup();
|
||||||
|
|
||||||
|
status_t _AddRepositories();
|
||||||
|
RepositoryInfo* _GetRepositoryInfo(
|
||||||
|
BSolverRepository* repository) const;
|
||||||
|
BSolverPackage* _GetPackage(Solvable* solvable) const;
|
||||||
|
BSolverPackage* _GetPackage(Id solvableId) const;
|
||||||
|
|
||||||
|
status_t _AddProblem(Id problemId);
|
||||||
|
status_t _GetResolvableExpression(Id id,
|
||||||
|
BPackageResolvableExpression& _expression)
|
||||||
|
const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Pool* fPool;
|
||||||
|
Solver* fSolver;
|
||||||
|
RepositoryInfoList fRepositoryInfos;
|
||||||
|
RepositoryInfo* fInstalledRepository;
|
||||||
|
SolvableMap fSolvablePackages;
|
||||||
|
ProblemList fProblems;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // HAIKU_LIBSOLV_SOLVER_H
|
||||||
@@ -9,348 +9,62 @@
|
|||||||
|
|
||||||
#include <package/solver/Solver.h>
|
#include <package/solver/Solver.h>
|
||||||
|
|
||||||
#include <new>
|
#include <dlfcn.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <solv/pool.h>
|
|
||||||
#include <solv/poolarch.h>
|
|
||||||
#include <solv/repo.h>
|
|
||||||
#include <solv/repo_haiku.h>
|
|
||||||
#include <solv/selection.h>
|
|
||||||
#include <solv/solver.h>
|
|
||||||
|
|
||||||
#include <package/RepositoryCache.h>
|
|
||||||
#include <package/solver/SolverPackageSpecifier.h>
|
|
||||||
#include <package/solver/SolverPackageSpecifierList.h>
|
|
||||||
#include <package/solver/SolverRepository.h>
|
|
||||||
|
|
||||||
#include <ObjectList.h>
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: libsolv doesn't have any helpful out-of-memory handling. It just just
|
|
||||||
// abort()s. Obviously that isn't good behavior for a library.
|
|
||||||
|
|
||||||
|
|
||||||
namespace BPackageKit {
|
namespace BPackageKit {
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - BSolver::Implementation
|
typedef BSolver* CreateSolverFunction();
|
||||||
|
static CreateSolverFunction* sCreateSolver = NULL;
|
||||||
|
|
||||||
|
static pthread_once_t sLoadLibsolvSolverAddOnInitOnce = PTHREAD_ONCE_INIT;
|
||||||
|
|
||||||
|
|
||||||
class BSolver::Implementation {
|
static void
|
||||||
public:
|
load_libsolv_solver_add_on()
|
||||||
Implementation();
|
{
|
||||||
~Implementation();
|
void* imageHandle = dlopen("libpackage-add-on-libsolv.so", 0);
|
||||||
|
if (imageHandle == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
status_t Init();
|
sCreateSolver = (CreateSolverFunction*)dlsym(imageHandle, "create_solver");
|
||||||
|
if (sCreateSolver == NULL)
|
||||||
status_t AddRepository(BSolverRepository* repository);
|
dlclose(imageHandle);
|
||||||
|
}
|
||||||
status_t Install(
|
|
||||||
const BSolverPackageSpecifierList&
|
|
||||||
packages);
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct SolvQueue;
|
|
||||||
struct RepositoryInfo;
|
|
||||||
|
|
||||||
typedef BObjectList<RepositoryInfo> RepositoryInfoList;
|
|
||||||
|
|
||||||
private:
|
|
||||||
status_t _AddRepositories();
|
|
||||||
RepositoryInfo* _GetRepositoryInfo(
|
|
||||||
BSolverRepository* repository) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Pool* fPool;
|
|
||||||
RepositoryInfoList fRepositoryInfos;
|
|
||||||
RepositoryInfo* fInstalledRepository;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct BSolver::Implementation::SolvQueue : Queue {
|
|
||||||
SolvQueue()
|
|
||||||
{
|
|
||||||
queue_init(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
~SolvQueue()
|
|
||||||
{
|
|
||||||
queue_free(this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct BSolver::Implementation::RepositoryInfo {
|
|
||||||
RepositoryInfo(BSolverRepository* repository)
|
|
||||||
:
|
|
||||||
fRepository(repository),
|
|
||||||
fSolvRepo(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BSolverRepository* Repository() const
|
|
||||||
{
|
|
||||||
return fRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
Repo* SolvRepo()
|
|
||||||
{
|
|
||||||
return fSolvRepo;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetSolvRepo(Repo* repo)
|
|
||||||
{
|
|
||||||
fSolvRepo = repo;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
BSolverRepository* fRepository;
|
|
||||||
Repo* fSolvRepo;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - BSolver
|
|
||||||
|
|
||||||
|
|
||||||
BSolver::BSolver()
|
BSolver::BSolver()
|
||||||
:
|
|
||||||
fImplementation(new(std::nothrow) Implementation)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BSolver::~BSolver()
|
BSolver::~BSolver()
|
||||||
{
|
{
|
||||||
delete fImplementation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
/*static*/ status_t
|
||||||
BSolver::Init()
|
BSolver::Create(BSolver*& _solver)
|
||||||
{
|
{
|
||||||
return fImplementation != NULL ? fImplementation->Init() : B_NO_MEMORY;
|
pthread_once(&sLoadLibsolvSolverAddOnInitOnce, &load_libsolv_solver_add_on);
|
||||||
}
|
if (sCreateSolver == NULL)
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
BSolver* solver = sCreateSolver();
|
||||||
status_t
|
if (solver == NULL)
|
||||||
BSolver::AddRepository(BSolverRepository* repository)
|
|
||||||
{
|
|
||||||
return fImplementation != NULL
|
|
||||||
? fImplementation->AddRepository(repository) : B_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BSolver::Install(const BSolverPackageSpecifierList& packages)
|
|
||||||
{
|
|
||||||
return fImplementation != NULL
|
|
||||||
? fImplementation->Install(packages) : B_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - BSolver::Implementation
|
|
||||||
|
|
||||||
|
|
||||||
BSolver::Implementation::Implementation()
|
|
||||||
:
|
|
||||||
fPool(NULL),
|
|
||||||
fRepositoryInfos(),
|
|
||||||
fInstalledRepository(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BSolver::Implementation::~Implementation()
|
|
||||||
{
|
|
||||||
if (fPool != NULL)
|
|
||||||
pool_free(fPool);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BSolver::Implementation::Init()
|
|
||||||
{
|
|
||||||
// already initialized?
|
|
||||||
if (fPool != NULL)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
fPool = pool_create();
|
|
||||||
|
|
||||||
// Set the system architecture. We use what uname() returns unless we're on
|
|
||||||
// x86 gcc2.
|
|
||||||
{
|
|
||||||
const char* arch;
|
|
||||||
#ifdef __HAIKU_ARCH_X86
|
|
||||||
#if (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_2
|
|
||||||
arch = "x86_gcc2";
|
|
||||||
#else
|
|
||||||
arch = "x86";
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
struct utsname info;
|
|
||||||
if (uname(&info) != 0)
|
|
||||||
return errno;
|
|
||||||
arch = info.machine;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pool_setarchpolicy(fPool, arch);
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BSolver::Implementation::AddRepository(BSolverRepository* repository)
|
|
||||||
{
|
|
||||||
if (repository == NULL || repository->InitCheck() != B_OK)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
// If the repository represents installed packages, check, if we already
|
|
||||||
// have such a repository.
|
|
||||||
if (repository->IsInstalled() && fInstalledRepository != NULL)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
// add the repository info
|
|
||||||
RepositoryInfo* info = new(std::nothrow) RepositoryInfo(repository);
|
|
||||||
if (info == NULL)
|
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
if (!fRepositoryInfos.AddItem(info)) {
|
status_t error = solver->Init();
|
||||||
delete info;
|
if (error != B_OK) {
|
||||||
return B_NO_MEMORY;
|
delete solver;
|
||||||
}
|
|
||||||
|
|
||||||
if (repository->IsInstalled())
|
|
||||||
fInstalledRepository = info;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BSolver::Implementation::Install(const BSolverPackageSpecifierList& packages)
|
|
||||||
{
|
|
||||||
if (packages.IsEmpty())
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
// TODO: Clean up first?
|
|
||||||
|
|
||||||
// add repositories to pool
|
|
||||||
status_t error = _AddRepositories();
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
// prepare pool for solving
|
|
||||||
pool_createwhatprovides(fPool);
|
|
||||||
|
|
||||||
// add the packages to install to the job queue
|
|
||||||
SolvQueue jobs;
|
|
||||||
|
|
||||||
int32 packageCount = packages.CountSpecifiers();
|
|
||||||
for (int32 i = 0; i < packageCount; i++) {
|
|
||||||
const BSolverPackageSpecifier& specifier = *packages.SpecifierAt(i);
|
|
||||||
|
|
||||||
// find matching packages
|
|
||||||
SolvQueue matchingPackages;
|
|
||||||
|
|
||||||
int flags = SELECTION_NAME | SELECTION_PROVIDES | SELECTION_GLOB
|
|
||||||
| SELECTION_CANON | SELECTION_DOTARCH | SELECTION_REL;
|
|
||||||
// TODO: All flags needed/useful?
|
|
||||||
/*int matchFlags =*/ selection_make(fPool, &matchingPackages,
|
|
||||||
specifier.Expression().Name(), flags);
|
|
||||||
// TODO: Don't just match the name, but also the version, if given!
|
|
||||||
if (matchingPackages.count == 0)
|
|
||||||
return B_NAME_NOT_FOUND;
|
|
||||||
|
|
||||||
// restrict to the matching repository
|
|
||||||
if (BSolverRepository* repository = specifier.Repository()) {
|
|
||||||
RepositoryInfo* repositoryInfo = _GetRepositoryInfo(repository);
|
|
||||||
if (repositoryInfo == NULL)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
SolvQueue repoFilter;
|
|
||||||
queue_push2(&repoFilter,
|
|
||||||
SOLVER_SOLVABLE_REPO/* | SOLVER_SETREPO | SOLVER_SETVENDOR*/,
|
|
||||||
repositoryInfo->SolvRepo()->repoid);
|
|
||||||
|
|
||||||
selection_filter(fPool, &matchingPackages, &repoFilter);
|
|
||||||
|
|
||||||
if (matchingPackages.count == 0)
|
|
||||||
return B_NAME_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < matchingPackages.count; j++)
|
|
||||||
queue_push(&jobs, matchingPackages.elements[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add solver mode to job queue elements
|
|
||||||
int solverMode = SOLVER_INSTALL;
|
|
||||||
for (int i = 0; i < jobs.count; i += 2) {
|
|
||||||
jobs.elements[i] |= solverMode;
|
|
||||||
// if (cleandeps)
|
|
||||||
// jobs.elements[i] |= SOLVER_CLEANDEPS;
|
|
||||||
// if (forcebest)
|
|
||||||
// jobs.elements[i] |= SOLVER_FORCEBEST;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the solver and solve
|
|
||||||
Solver* solver = solver_create(fPool);
|
|
||||||
solver_set_flag(solver, SOLVER_FLAG_SPLITPROVIDES, 1);
|
|
||||||
solver_set_flag(solver, SOLVER_FLAG_BEST_OBEY_POLICY, 1);
|
|
||||||
|
|
||||||
int problemCount = solver_solve(solver, &jobs);
|
|
||||||
solver_free(solver);
|
|
||||||
|
|
||||||
// TODO: Problem support!
|
|
||||||
return problemCount == 0 ? B_OK : B_BAD_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BSolver::Implementation::_AddRepositories()
|
|
||||||
{
|
|
||||||
if (fInstalledRepository == NULL)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
int32 repositoryCount = fRepositoryInfos.CountItems();
|
|
||||||
for (int32 i = 0; i < repositoryCount; i++) {
|
|
||||||
RepositoryInfo* repositoryInfo = fRepositoryInfos.ItemAt(i);
|
|
||||||
BSolverRepository* repository = repositoryInfo->Repository();
|
|
||||||
Repo* repo = repo_create(fPool, repository->Name());
|
|
||||||
repositoryInfo->SetSolvRepo(repo);
|
|
||||||
|
|
||||||
repo->priority = 256 - repository->Priority();
|
|
||||||
repo->appdata = (void*)repositoryInfo;
|
|
||||||
|
|
||||||
BRepositoryCache::Iterator it = repository->GetIterator();
|
|
||||||
while (const BPackageInfo* packageInfo = it.Next()) {
|
|
||||||
repo_add_haiku_package_info(repo, *packageInfo,
|
|
||||||
REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
repo_internalize(repo);
|
|
||||||
|
|
||||||
if (repository->IsInstalled())
|
|
||||||
pool_set_installed(fPool, repo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_solver = solver;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BSolver::Implementation::RepositoryInfo*
|
|
||||||
BSolver::Implementation::_GetRepositoryInfo(BSolverRepository* repository) const
|
|
||||||
{
|
|
||||||
int32 repositoryCount = fRepositoryInfos.CountItems();
|
|
||||||
for (int32 i = 0; i < repositoryCount; i++) {
|
|
||||||
RepositoryInfo* repositoryInfo = fRepositoryInfos.ItemAt(i);
|
|
||||||
if (repository == repositoryInfo->Repository())
|
|
||||||
return repositoryInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace BPackageKit
|
} // namespace BPackageKit
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ingo Weinhold <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <package/solver/SolverPackage.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPackageKit {
|
||||||
|
|
||||||
|
|
||||||
|
BSolverPackage::BSolverPackage(BSolverRepository* repository,
|
||||||
|
const BPackageInfo& packageInfo)
|
||||||
|
:
|
||||||
|
fRepository(repository),
|
||||||
|
fInfo(packageInfo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverPackage::BSolverPackage(const BSolverPackage& other)
|
||||||
|
:
|
||||||
|
fRepository(other.fRepository),
|
||||||
|
fInfo(other.fInfo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverPackage::~BSolverPackage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverRepository*
|
||||||
|
BSolverPackage::Repository() const
|
||||||
|
{
|
||||||
|
return fRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BPackageInfo&
|
||||||
|
BSolverPackage::Info() const
|
||||||
|
{
|
||||||
|
return fInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
BSolverPackage::Name() const
|
||||||
|
{
|
||||||
|
return fInfo.Name();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
BSolverPackage::VersionedName() const
|
||||||
|
{
|
||||||
|
if (fInfo.Version().InitCheck() != B_OK)
|
||||||
|
return Name();
|
||||||
|
BString result = Name();
|
||||||
|
return result << '-' << fInfo.Version().ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverPackage&
|
||||||
|
BSolverPackage::operator=(const BSolverPackage& other)
|
||||||
|
{
|
||||||
|
fRepository = other.fRepository;
|
||||||
|
fInfo = other.fInfo;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace BPackageKit
|
||||||
@@ -101,6 +101,13 @@ BSolverPackageSpecifierList::AppendSpecifier(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BSolverPackageSpecifierList::MakeEmpty()
|
||||||
|
{
|
||||||
|
fSpecifiers->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BSolverPackageSpecifierList&
|
BSolverPackageSpecifierList&
|
||||||
BSolverPackageSpecifierList::operator=(const BSolverPackageSpecifierList& other)
|
BSolverPackageSpecifierList::operator=(const BSolverPackageSpecifierList& other)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ingo Weinhold <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <package/solver/SolverProblem.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <package/solver/SolverPackage.h>
|
||||||
|
|
||||||
|
|
||||||
|
static const char* const kToStringTexts[] = {
|
||||||
|
"unspecified problem",
|
||||||
|
"%source% does not belong to a distupgrade repository",
|
||||||
|
"%source% has inferior architecture",
|
||||||
|
"problem with installed package %source%",
|
||||||
|
"conflicting requests",
|
||||||
|
"nothing provides requested %dependency%",
|
||||||
|
"%dependency% is provided by the system",
|
||||||
|
"dependency problem",
|
||||||
|
"package %source% is not installable",
|
||||||
|
"nothing provides %dependency% needed by %source%",
|
||||||
|
"cannot install both %source% and %target%",
|
||||||
|
"package %source% conflicts with %dependency% provided by %target%",
|
||||||
|
"package %source% obsoletes %dependency% provided by %target%",
|
||||||
|
"installed package %source% obsoletes %dependency% provided by %target%",
|
||||||
|
"package %source% implicitly obsoletes %dependency% provided by %target%",
|
||||||
|
"package %source% requires %dependency%, but none of the providers can be "
|
||||||
|
"installed",
|
||||||
|
"package %source% conflicts with %dependency% provided by itself"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPackageKit {
|
||||||
|
|
||||||
|
|
||||||
|
BSolverProblem::BSolverProblem(BType type, BSolverPackage* sourcePackage,
|
||||||
|
BSolverPackage* targetPackage)
|
||||||
|
:
|
||||||
|
fType(type),
|
||||||
|
fSourcePackage(sourcePackage),
|
||||||
|
fTargetPackage(targetPackage),
|
||||||
|
fDependency()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverProblem::BSolverProblem(BType type, BSolverPackage* sourcePackage,
|
||||||
|
BSolverPackage* targetPackage,
|
||||||
|
const BPackageResolvableExpression& dependency)
|
||||||
|
:
|
||||||
|
fType(type),
|
||||||
|
fSourcePackage(sourcePackage),
|
||||||
|
fTargetPackage(targetPackage),
|
||||||
|
fDependency(dependency)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverProblem::~BSolverProblem()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverProblem::BType
|
||||||
|
BSolverProblem::Type() const
|
||||||
|
{
|
||||||
|
return fType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverPackage*
|
||||||
|
BSolverProblem::SourcePackage() const
|
||||||
|
{
|
||||||
|
return fSourcePackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverPackage*
|
||||||
|
BSolverProblem::TargetPackage() const
|
||||||
|
{
|
||||||
|
return fTargetPackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BPackageResolvableExpression&
|
||||||
|
BSolverProblem::Dependency() const
|
||||||
|
{
|
||||||
|
return fDependency;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
BSolverProblem::ToString() const
|
||||||
|
{
|
||||||
|
size_t index = fType;
|
||||||
|
if (index >= sizeof(kToStringTexts) / sizeof(kToStringTexts[0]))
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
return BString(kToStringTexts[index])
|
||||||
|
.ReplaceAll("%source%",
|
||||||
|
fSourcePackage != NULL
|
||||||
|
? fSourcePackage->VersionedName().String() : "?")
|
||||||
|
.ReplaceAll("%target%",
|
||||||
|
fTargetPackage != NULL
|
||||||
|
? fTargetPackage->VersionedName().String() : "?")
|
||||||
|
.ReplaceAll("%dependency%",
|
||||||
|
fDependency.InitCheck() == B_OK
|
||||||
|
? fDependency.ToString().String() : "?");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace BPackageKit
|
||||||
@@ -13,6 +13,10 @@
|
|||||||
#include <package/PackageRoster.h>
|
#include <package/PackageRoster.h>
|
||||||
#include <package/RepositoryCache.h>
|
#include <package/RepositoryCache.h>
|
||||||
#include <package/RepositoryConfig.h>
|
#include <package/RepositoryConfig.h>
|
||||||
|
#include <package/solver/SolverPackage.h>
|
||||||
|
|
||||||
|
|
||||||
|
static const int32 kInitialPackageListSize = 40;
|
||||||
|
|
||||||
|
|
||||||
namespace BPackageKit {
|
namespace BPackageKit {
|
||||||
@@ -23,7 +27,7 @@ BSolverRepository::BSolverRepository()
|
|||||||
fName(),
|
fName(),
|
||||||
fPriority(0),
|
fPriority(0),
|
||||||
fIsInstalled(false),
|
fIsInstalled(false),
|
||||||
fPackages()
|
fPackages(kInitialPackageListSize, true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +37,7 @@ BSolverRepository::BSolverRepository(const BString& name)
|
|||||||
fName(),
|
fName(),
|
||||||
fPriority(0),
|
fPriority(0),
|
||||||
fIsInstalled(false),
|
fIsInstalled(false),
|
||||||
fPackages()
|
fPackages(kInitialPackageListSize, true)
|
||||||
{
|
{
|
||||||
SetTo(name);
|
SetTo(name);
|
||||||
}
|
}
|
||||||
@@ -44,7 +48,7 @@ BSolverRepository::BSolverRepository(BPackageInstallationLocation location)
|
|||||||
fName(),
|
fName(),
|
||||||
fPriority(0),
|
fPriority(0),
|
||||||
fIsInstalled(false),
|
fIsInstalled(false),
|
||||||
fPackages()
|
fPackages(kInitialPackageListSize, true)
|
||||||
{
|
{
|
||||||
SetTo(location);
|
SetTo(location);
|
||||||
}
|
}
|
||||||
@@ -55,7 +59,7 @@ BSolverRepository::BSolverRepository(BAllInstallationLocations)
|
|||||||
fName(),
|
fName(),
|
||||||
fPriority(0),
|
fPriority(0),
|
||||||
fIsInstalled(false),
|
fIsInstalled(false),
|
||||||
fPackages()
|
fPackages(kInitialPackageListSize, true)
|
||||||
{
|
{
|
||||||
SetTo(B_ALL_INSTALLATION_LOCATIONS);
|
SetTo(B_ALL_INSTALLATION_LOCATIONS);
|
||||||
}
|
}
|
||||||
@@ -66,7 +70,7 @@ BSolverRepository::BSolverRepository(const BRepositoryConfig& config)
|
|||||||
fName(),
|
fName(),
|
||||||
fPriority(0),
|
fPriority(0),
|
||||||
fIsInstalled(false),
|
fIsInstalled(false),
|
||||||
fPackages()
|
fPackages(kInitialPackageListSize, true)
|
||||||
{
|
{
|
||||||
SetTo(config);
|
SetTo(config);
|
||||||
}
|
}
|
||||||
@@ -184,6 +188,13 @@ BSolverRepository::IsInstalled() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BSolverRepository::SetInstalled(bool isInstalled)
|
||||||
|
{
|
||||||
|
fIsInstalled = isInstalled;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BString
|
BString
|
||||||
BSolverRepository::Name() const
|
BSolverRepository::Name() const
|
||||||
{
|
{
|
||||||
@@ -198,10 +209,37 @@ BSolverRepository::Priority() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BSolverRepository::IsEmpty() const
|
||||||
|
{
|
||||||
|
return fPackages.IsEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
BSolverRepository::CountPackages() const
|
||||||
|
{
|
||||||
|
return fPackages.CountItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverPackage*
|
||||||
|
BSolverRepository::PackageAt(int32 index) const
|
||||||
|
{
|
||||||
|
return fPackages.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BSolverRepository::AddPackage(const BPackageInfo& info)
|
BSolverRepository::AddPackage(const BPackageInfo& info)
|
||||||
{
|
{
|
||||||
return fPackages.AddInfo(info);
|
BSolverPackage* package = new(std::nothrow) BSolverPackage(this, info);
|
||||||
|
if (package == NULL || !fPackages.AddItem(package)) {
|
||||||
|
delete package;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -216,7 +254,7 @@ BSolverRepository::AddPackages(BPackageInstallationLocation location)
|
|||||||
|
|
||||||
BRepositoryCache::Iterator it = packageInfos.GetIterator();
|
BRepositoryCache::Iterator it = packageInfos.GetIterator();
|
||||||
while (const BPackageInfo* packageInfo = it.Next()) {
|
while (const BPackageInfo* packageInfo = it.Next()) {
|
||||||
error = fPackages.AddInfo(*packageInfo);
|
error = AddPackage(*packageInfo);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -225,11 +263,4 @@ BSolverRepository::AddPackages(BPackageInstallationLocation location)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BSolverRepository::Iterator
|
|
||||||
BSolverRepository::GetIterator() const
|
|
||||||
{
|
|
||||||
return fPackages.GetIterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace BPackageKit
|
} // namespace BPackageKit
|
||||||
|
|||||||
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ingo Weinhold <ingo_weinhold@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <package/solver/SolverResult.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPackageKit {
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - BSolverResultElement
|
||||||
|
|
||||||
|
|
||||||
|
BSolverResultElement::BSolverResultElement(BType type, BSolverPackage* package)
|
||||||
|
:
|
||||||
|
fType(type),
|
||||||
|
fPackage(package)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverResultElement::BSolverResultElement(const BSolverResultElement& other)
|
||||||
|
:
|
||||||
|
fType(other.fType),
|
||||||
|
fPackage(other.fPackage)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverResultElement::~BSolverResultElement()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverResultElement::BType
|
||||||
|
BSolverResultElement::Type() const
|
||||||
|
{
|
||||||
|
return fType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverPackage*
|
||||||
|
BSolverResultElement::Package() const
|
||||||
|
{
|
||||||
|
return fPackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverResultElement&
|
||||||
|
BSolverResultElement::operator=(const BSolverResultElement& other)
|
||||||
|
{
|
||||||
|
fType = other.fType;
|
||||||
|
fPackage = other.fPackage;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - BSolverResult
|
||||||
|
|
||||||
|
|
||||||
|
BSolverResult::BSolverResult()
|
||||||
|
:
|
||||||
|
fElements(20, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSolverResult::~BSolverResult()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BSolverResult::IsEmpty() const
|
||||||
|
{
|
||||||
|
return fElements.IsEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
BSolverResult::CountElements() const
|
||||||
|
{
|
||||||
|
return fElements.CountItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BSolverResultElement*
|
||||||
|
BSolverResult::ElementAt(int32 index) const
|
||||||
|
{
|
||||||
|
return fElements.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BSolverResult::MakeEmpty()
|
||||||
|
{
|
||||||
|
fElements.MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BSolverResult::AppendElement(const BSolverResultElement& element)
|
||||||
|
{
|
||||||
|
BSolverResultElement* newElement
|
||||||
|
= new(std::nothrow) BSolverResultElement(element);
|
||||||
|
if (newElement == NULL || !fElements.AddItem(newElement)) {
|
||||||
|
delete newElement;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace BPackageKit
|
||||||
Reference in New Issue
Block a user