pkgman: Move some classes into own file for reuse
Namely RepositoryBuilder and PackageInfoErrorListener.
This commit is contained in:
@@ -5,12 +5,14 @@ UsePrivateHeaders shared support ;
|
|||||||
BinCommand pkgman :
|
BinCommand pkgman :
|
||||||
command_add_repo.cpp
|
command_add_repo.cpp
|
||||||
command_drop_repo.cpp
|
command_drop_repo.cpp
|
||||||
command_resolve_dependencies.cpp
|
|
||||||
command_list_repos.cpp
|
command_list_repos.cpp
|
||||||
command_refresh.cpp
|
command_refresh.cpp
|
||||||
|
command_resolve_dependencies.cpp
|
||||||
DecisionProvider.cpp
|
DecisionProvider.cpp
|
||||||
JobStateListener.cpp
|
JobStateListener.cpp
|
||||||
|
PackageInfoErrorListener.cpp
|
||||||
pkgman.cpp
|
pkgman.cpp
|
||||||
|
RepositoryBuilder.cpp
|
||||||
:
|
:
|
||||||
package be
|
package be
|
||||||
$(TARGET_LIBSUPC++)
|
$(TARGET_LIBSUPC++)
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ingo Weinhold <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "PackageInfoErrorListener.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
PackageInfoErrorListener::PackageInfoErrorListener(const BString& errorContext)
|
||||||
|
:
|
||||||
|
fErrorContext(errorContext)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageInfoErrorListener::OnError(const BString& message, int line, int column)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: Parse error in line %d:%d: %s\n",
|
||||||
|
fErrorContext.String(), line, column, message.String());
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ingo Weinhold <[email protected]>
|
||||||
|
*/
|
||||||
|
#ifndef PACKAGE_INFO_ERROR_LISTENER_H
|
||||||
|
#define PACKAGE_INFO_ERROR_LISTENER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <package/PackageInfo.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace BPackageKit;
|
||||||
|
|
||||||
|
|
||||||
|
class PackageInfoErrorListener : public BPackageInfo::ParseErrorListener {
|
||||||
|
public:
|
||||||
|
PackageInfoErrorListener(
|
||||||
|
const BString& errorContext);
|
||||||
|
|
||||||
|
virtual void OnError(const BString& message, int line,
|
||||||
|
int column);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BString fErrorContext;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // PACKAGE_INFO_ERROR_LISTENER_H
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ingo Weinhold <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "RepositoryBuilder.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
#include <Entry.h>
|
||||||
|
#include <Path.h>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
#include "PackageInfoErrorListener.h"
|
||||||
|
#include "pkgman.h"
|
||||||
|
|
||||||
|
|
||||||
|
RepositoryBuilder::RepositoryBuilder(BSolverRepository& repository,
|
||||||
|
const BString& name, const BString& errorName)
|
||||||
|
:
|
||||||
|
fRepository(repository),
|
||||||
|
fErrorName(errorName.IsEmpty() ? name : errorName),
|
||||||
|
fPackagePaths(NULL)
|
||||||
|
{
|
||||||
|
status_t error = fRepository.SetTo(name);
|
||||||
|
if (error != B_OK)
|
||||||
|
DIE(error, "failed to init %s repository", fErrorName.String());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RepositoryBuilder&
|
||||||
|
RepositoryBuilder::SetPackagePathMap(PackagePathMap* packagePaths)
|
||||||
|
{
|
||||||
|
fPackagePaths = packagePaths;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RepositoryBuilder&
|
||||||
|
RepositoryBuilder::AddPackage(const BPackageInfo& info,
|
||||||
|
const char* packageErrorName, BSolverPackage** _package)
|
||||||
|
{
|
||||||
|
status_t error = fRepository.AddPackage(info, _package);
|
||||||
|
if (error != B_OK) {
|
||||||
|
DIE(error, "failed to add %s to %s repository",
|
||||||
|
packageErrorName != NULL
|
||||||
|
? packageErrorName
|
||||||
|
: (BString("package ") << info.Name()).String(),
|
||||||
|
fErrorName.String());
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RepositoryBuilder&
|
||||||
|
RepositoryBuilder::AddPackage(const char* path, BSolverPackage** _package)
|
||||||
|
{
|
||||||
|
// read a package info from the (HPKG or package info) file
|
||||||
|
BPackageInfo packageInfo;
|
||||||
|
|
||||||
|
size_t pathLength = strlen(path);
|
||||||
|
status_t error;
|
||||||
|
if (pathLength > 5 && strcmp(path + pathLength - 5, ".hpkg") == 0) {
|
||||||
|
// a package file
|
||||||
|
error = packageInfo.ReadFromPackageFile(path);
|
||||||
|
} else {
|
||||||
|
// a package info file (supposedly)
|
||||||
|
PackageInfoErrorListener errorListener(
|
||||||
|
"Error: failed to read package info");
|
||||||
|
error = packageInfo.ReadFromConfigFile(BEntry(path),
|
||||||
|
&errorListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error != B_OK)
|
||||||
|
DIE(errno, "failed to read package info from \"%s\"", path);
|
||||||
|
|
||||||
|
// add the package
|
||||||
|
BSolverPackage* package;
|
||||||
|
AddPackage(packageInfo, path, &package);
|
||||||
|
|
||||||
|
// enter the package path in the path map, if given
|
||||||
|
if (fPackagePaths != NULL)
|
||||||
|
(*fPackagePaths)[package] = path;
|
||||||
|
|
||||||
|
if (_package != NULL)
|
||||||
|
*_package = package;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RepositoryBuilder&
|
||||||
|
RepositoryBuilder::AddPackages(BPackageInstallationLocation location,
|
||||||
|
const char* locationErrorName)
|
||||||
|
{
|
||||||
|
status_t error = fRepository.AddPackages(location);
|
||||||
|
if (error != B_OK) {
|
||||||
|
DIE(error, "failed to add %s packages to %s repository",
|
||||||
|
locationErrorName, fErrorName.String());
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RepositoryBuilder&
|
||||||
|
RepositoryBuilder::AddPackagesDirectory(const char* path)
|
||||||
|
{
|
||||||
|
// open directory
|
||||||
|
DIR* dir = opendir(path);
|
||||||
|
if (dir == NULL)
|
||||||
|
DIE(errno, "failed to open package directory \"%s\"", path);
|
||||||
|
CObjectDeleter<DIR, int> dirCloser(dir, &closedir);
|
||||||
|
|
||||||
|
// iterate through directory entries
|
||||||
|
while (dirent* entry = readdir(dir)) {
|
||||||
|
// skip "." and ".."
|
||||||
|
const char* name = entry->d_name;
|
||||||
|
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// stat() the entry and skip any non-file
|
||||||
|
BPath entryPath;
|
||||||
|
status_t error = entryPath.SetTo(path, name);
|
||||||
|
if (error != B_OK)
|
||||||
|
DIE(errno, "failed to construct path");
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
if (lstat(entryPath.Path(), &st) != 0)
|
||||||
|
DIE(errno, "failed to stat() %s", entryPath.Path());
|
||||||
|
|
||||||
|
if (!S_ISREG(st.st_mode))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
AddPackage(entryPath.Path());
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RepositoryBuilder&
|
||||||
|
RepositoryBuilder::AddToSolver(BSolver* solver, bool isInstalled)
|
||||||
|
{
|
||||||
|
fRepository.SetInstalled(isInstalled);
|
||||||
|
|
||||||
|
status_t error = solver->AddRepository(&fRepository);
|
||||||
|
if (error != B_OK) {
|
||||||
|
DIE(error, "failed to add %s repository to solver",
|
||||||
|
fErrorName.String());
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ingo Weinhold <[email protected]>
|
||||||
|
*/
|
||||||
|
#ifndef REPOSITORY_BUILDER_H
|
||||||
|
#define REPOSITORY_BUILDER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <package/PackageInfo.h>
|
||||||
|
#include <package/solver/Solver.h>
|
||||||
|
#include <package/solver/SolverPackage.h>
|
||||||
|
#include <package/solver/SolverRepository.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace BPackageKit;
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::map<BSolverPackage*, BString> PackagePathMap;
|
||||||
|
|
||||||
|
|
||||||
|
class RepositoryBuilder {
|
||||||
|
private:
|
||||||
|
typedef RepositoryBuilder Builder;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RepositoryBuilder(BSolverRepository& repository,
|
||||||
|
const BString& name,
|
||||||
|
const BString& errorName = BString());
|
||||||
|
|
||||||
|
RepositoryBuilder& SetPackagePathMap(PackagePathMap* packagePaths);
|
||||||
|
|
||||||
|
RepositoryBuilder& AddPackage(const BPackageInfo& info,
|
||||||
|
const char* packageErrorName = NULL,
|
||||||
|
BSolverPackage** _package = NULL);
|
||||||
|
RepositoryBuilder& AddPackage(const char* path,
|
||||||
|
BSolverPackage** _package = NULL);
|
||||||
|
RepositoryBuilder& AddPackages(
|
||||||
|
BPackageInstallationLocation location,
|
||||||
|
const char* locationErrorName);
|
||||||
|
RepositoryBuilder& AddPackagesDirectory(const char* path);
|
||||||
|
|
||||||
|
RepositoryBuilder& AddToSolver(BSolver* solver,
|
||||||
|
bool isInstalled = false);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BSolverRepository& fRepository;
|
||||||
|
BString fErrorName;
|
||||||
|
PackagePathMap* fPackagePaths;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // REPOSITORY_BUILDER_H
|
||||||
@@ -7,31 +7,21 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include <Entry.h>
|
|
||||||
#include <File.h>
|
|
||||||
#include <Path.h>
|
|
||||||
|
|
||||||
#include <package/PackageInfo.h>
|
|
||||||
#include <package/solver/Solver.h>
|
|
||||||
#include <package/solver/SolverPackage.h>
|
|
||||||
#include <package/solver/SolverPackageSpecifier.h>
|
#include <package/solver/SolverPackageSpecifier.h>
|
||||||
#include <package/solver/SolverPackageSpecifierList.h>
|
#include <package/solver/SolverPackageSpecifierList.h>
|
||||||
#include <package/solver/SolverProblem.h>
|
#include <package/solver/SolverProblem.h>
|
||||||
#include <package/solver/SolverRepository.h>
|
|
||||||
#include <package/solver/SolverResult.h>
|
#include <package/solver/SolverResult.h>
|
||||||
|
|
||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
#include "pkgman.h"
|
#include "pkgman.h"
|
||||||
|
#include "RepositoryBuilder.h"
|
||||||
|
|
||||||
|
|
||||||
// TODO: internationalization!
|
// TODO: internationalization!
|
||||||
@@ -40,9 +30,6 @@
|
|||||||
using namespace BPackageKit;
|
using namespace BPackageKit;
|
||||||
|
|
||||||
|
|
||||||
typedef std::map<BSolverPackage*, BString> PackagePathMap;
|
|
||||||
|
|
||||||
|
|
||||||
static const char* kCommandUsage =
|
static const char* kCommandUsage =
|
||||||
"Usage: %s resolve-dependencies <package> <repository> [ <priority> ] ...\n"
|
"Usage: %s resolve-dependencies <package> <repository> [ <priority> ] ...\n"
|
||||||
"Resolves and lists all packages a given package depends on. Fails, if\n"
|
"Resolves and lists all packages a given package depends on. Fails, if\n"
|
||||||
@@ -71,158 +58,6 @@ print_command_usage_and_exit(bool error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct PackageInfoErrorListener : public BPackageInfo::ParseErrorListener {
|
|
||||||
public:
|
|
||||||
PackageInfoErrorListener(const BString& errorContext)
|
|
||||||
:
|
|
||||||
fErrorContext(errorContext)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void OnError(const BString& message, int line, int column)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s: Parse error in line %d:%d: %s\n",
|
|
||||||
fErrorContext.String(), line, column, message.String());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
BString fErrorContext;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct RepositoryBuilder {
|
|
||||||
RepositoryBuilder(BSolverRepository& repository, const BString& name,
|
|
||||||
const BString& errorName = BString())
|
|
||||||
:
|
|
||||||
fRepository(repository),
|
|
||||||
fErrorName(errorName.IsEmpty() ? name : errorName),
|
|
||||||
fPackagePaths(NULL)
|
|
||||||
{
|
|
||||||
status_t error = fRepository.SetTo(name);
|
|
||||||
if (error != B_OK)
|
|
||||||
DIE(error, "failed to init %s repository", fErrorName.String());
|
|
||||||
}
|
|
||||||
|
|
||||||
RepositoryBuilder& SetPackagePathMap(PackagePathMap* packagePaths)
|
|
||||||
{
|
|
||||||
fPackagePaths = packagePaths;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RepositoryBuilder& AddPackage(const BPackageInfo& info,
|
|
||||||
const char* packageErrorName = NULL, BSolverPackage** _package = NULL)
|
|
||||||
{
|
|
||||||
status_t error = fRepository.AddPackage(info, _package);
|
|
||||||
if (error != B_OK) {
|
|
||||||
DIE(error, "failed to add %s to %s repository",
|
|
||||||
packageErrorName != NULL
|
|
||||||
? packageErrorName
|
|
||||||
: (BString("package ") << info.Name()).String(),
|
|
||||||
fErrorName.String());
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RepositoryBuilder& AddPackage(const char* path,
|
|
||||||
BSolverPackage** _package = NULL)
|
|
||||||
{
|
|
||||||
// read a package info from the (HPKG or package info) file
|
|
||||||
BPackageInfo packageInfo;
|
|
||||||
|
|
||||||
size_t pathLength = strlen(path);
|
|
||||||
status_t error;
|
|
||||||
if (pathLength > 5 && strcmp(path + pathLength - 5, ".hpkg") == 0) {
|
|
||||||
// a package file
|
|
||||||
error = packageInfo.ReadFromPackageFile(path);
|
|
||||||
} else {
|
|
||||||
// a package info file (supposedly)
|
|
||||||
PackageInfoErrorListener errorListener(
|
|
||||||
"Error: failed to read package info");
|
|
||||||
error = packageInfo.ReadFromConfigFile(BEntry(path),
|
|
||||||
&errorListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error != B_OK)
|
|
||||||
DIE(errno, "failed to read package info from \"%s\"", path);
|
|
||||||
|
|
||||||
// add the package
|
|
||||||
BSolverPackage* package;
|
|
||||||
AddPackage(packageInfo, path, &package);
|
|
||||||
|
|
||||||
// enter the package path in the path map, if given
|
|
||||||
if (fPackagePaths != NULL)
|
|
||||||
(*fPackagePaths)[package] = path;
|
|
||||||
|
|
||||||
if (_package != NULL)
|
|
||||||
*_package = package;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RepositoryBuilder& AddPackages(BPackageInstallationLocation location,
|
|
||||||
const char* locationErrorName)
|
|
||||||
{
|
|
||||||
status_t error = fRepository.AddPackages(location);
|
|
||||||
if (error != B_OK) {
|
|
||||||
DIE(error, "failed to add %s packages to %s repository",
|
|
||||||
locationErrorName, fErrorName.String());
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RepositoryBuilder& AddPackagesDirectory(const char* path)
|
|
||||||
{
|
|
||||||
// open directory
|
|
||||||
DIR* dir = opendir(path);
|
|
||||||
if (dir == NULL)
|
|
||||||
DIE(errno, "failed to open package directory \"%s\"", path);
|
|
||||||
CObjectDeleter<DIR, int> dirCloser(dir, &closedir);
|
|
||||||
|
|
||||||
// iterate through directory entries
|
|
||||||
while (dirent* entry = readdir(dir)) {
|
|
||||||
// skip "." and ".."
|
|
||||||
const char* name = entry->d_name;
|
|
||||||
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// stat() the entry and skip any non-file
|
|
||||||
BPath entryPath;
|
|
||||||
status_t error = entryPath.SetTo(path, name);
|
|
||||||
if (error != B_OK)
|
|
||||||
DIE(errno, "failed to construct path");
|
|
||||||
|
|
||||||
struct stat st;
|
|
||||||
if (lstat(entryPath.Path(), &st) != 0)
|
|
||||||
DIE(errno, "failed to stat() %s", entryPath.Path());
|
|
||||||
|
|
||||||
if (!S_ISREG(st.st_mode))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
AddPackage(entryPath.Path());
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RepositoryBuilder& AddToSolver(BSolver* solver, bool isInstalled = false)
|
|
||||||
{
|
|
||||||
fRepository.SetInstalled(isInstalled);
|
|
||||||
|
|
||||||
status_t error = solver->AddRepository(&fRepository);
|
|
||||||
if (error != B_OK) {
|
|
||||||
DIE(error, "failed to add %s repository to solver",
|
|
||||||
fErrorName.String());
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
BSolverRepository& fRepository;
|
|
||||||
BString fErrorName;
|
|
||||||
PackagePathMap* fPackagePaths;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
check_problems(BSolver* solver, const char* errorContext)
|
check_problems(BSolver* solver, const char* errorContext)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user