From 5776551d3dfa5c88bdebd65fd211aaebbb91e525 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Wed, 10 Apr 2013 14:41:30 +0200 Subject: [PATCH] pkgman: Move some classes into own file for reuse Namely RepositoryBuilder and PackageInfoErrorListener. --- src/bin/pkgman/Jamfile | 4 +- src/bin/pkgman/PackageInfoErrorListener.cpp | 27 +++ src/bin/pkgman/PackageInfoErrorListener.h | 31 ++++ src/bin/pkgman/RepositoryBuilder.cpp | 158 +++++++++++++++++ src/bin/pkgman/RepositoryBuilder.h | 57 ++++++ .../pkgman/command_resolve_dependencies.cpp | 167 +----------------- 6 files changed, 277 insertions(+), 167 deletions(-) create mode 100644 src/bin/pkgman/PackageInfoErrorListener.cpp create mode 100644 src/bin/pkgman/PackageInfoErrorListener.h create mode 100644 src/bin/pkgman/RepositoryBuilder.cpp create mode 100644 src/bin/pkgman/RepositoryBuilder.h diff --git a/src/bin/pkgman/Jamfile b/src/bin/pkgman/Jamfile index f6dfa06b37..db1206a47f 100644 --- a/src/bin/pkgman/Jamfile +++ b/src/bin/pkgman/Jamfile @@ -5,12 +5,14 @@ UsePrivateHeaders shared support ; BinCommand pkgman : command_add_repo.cpp command_drop_repo.cpp - command_resolve_dependencies.cpp command_list_repos.cpp command_refresh.cpp + command_resolve_dependencies.cpp DecisionProvider.cpp JobStateListener.cpp + PackageInfoErrorListener.cpp pkgman.cpp + RepositoryBuilder.cpp : package be $(TARGET_LIBSUPC++) diff --git a/src/bin/pkgman/PackageInfoErrorListener.cpp b/src/bin/pkgman/PackageInfoErrorListener.cpp new file mode 100644 index 0000000000..89639c3d1b --- /dev/null +++ b/src/bin/pkgman/PackageInfoErrorListener.cpp @@ -0,0 +1,27 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold + */ + + +#include "PackageInfoErrorListener.h" + +#include + + +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()); +} diff --git a/src/bin/pkgman/PackageInfoErrorListener.h b/src/bin/pkgman/PackageInfoErrorListener.h new file mode 100644 index 0000000000..7bd9b1a865 --- /dev/null +++ b/src/bin/pkgman/PackageInfoErrorListener.h @@ -0,0 +1,31 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold + */ +#ifndef PACKAGE_INFO_ERROR_LISTENER_H +#define PACKAGE_INFO_ERROR_LISTENER_H + + +#include + + +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 diff --git a/src/bin/pkgman/RepositoryBuilder.cpp b/src/bin/pkgman/RepositoryBuilder.cpp new file mode 100644 index 0000000000..a307533c97 --- /dev/null +++ b/src/bin/pkgman/RepositoryBuilder.cpp @@ -0,0 +1,158 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold + */ + + +#include "RepositoryBuilder.h" + +#include +#include + +#include +#include + +#include + +#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 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; +} diff --git a/src/bin/pkgman/RepositoryBuilder.h b/src/bin/pkgman/RepositoryBuilder.h new file mode 100644 index 0000000000..0b9e72af58 --- /dev/null +++ b/src/bin/pkgman/RepositoryBuilder.h @@ -0,0 +1,57 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold + */ +#ifndef REPOSITORY_BUILDER_H +#define REPOSITORY_BUILDER_H + + +#include + +#include +#include +#include +#include + + +using namespace BPackageKit; + + +typedef std::map 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 diff --git a/src/bin/pkgman/command_resolve_dependencies.cpp b/src/bin/pkgman/command_resolve_dependencies.cpp index d71aed657f..9e67ced5a8 100644 --- a/src/bin/pkgman/command_resolve_dependencies.cpp +++ b/src/bin/pkgman/command_resolve_dependencies.cpp @@ -7,31 +7,21 @@ */ -#include #include #include #include #include #include -#include - -#include -#include -#include - -#include -#include -#include #include #include #include -#include #include #include #include "pkgman.h" +#include "RepositoryBuilder.h" // TODO: internationalization! @@ -40,9 +30,6 @@ using namespace BPackageKit; -typedef std::map PackagePathMap; - - static const char* kCommandUsage = "Usage: %s resolve-dependencies [ ] ...\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 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 check_problems(BSolver* solver, const char* errorContext) {