added 6 changesets to branch 'refs/remotes/weinhold-github/pm-flat' old head: 19f3eaaee692a5edc59cb453540489a132c43b69 new head: 7216c8944d01a0800e11a2e9f8d04ef307957f91 overview: https://github.com/weinhold/Haiku/compare/19f3eaa...7216c89 ---------------------------------------------------------------------------- 65502bb: BSolver: Add VerifyInstallation() ... and implement it in LibsolvSolver. 7498842: pkgman resolve-dependencies: Verify result * Make sure that the computed dependencies don't themselves depend on the specified package. * Print only the actual dependencies, not the specified package. a8b832b: BSolverRepository::AddPackage(): Add optional return parameter ... returning the added BSolverPackage object. 4b8aabf: pkgman resolve-dependencies: Print package paths ... instead of package name and version. The command should now work as required by haikuporter. 046f1c4: pkgman resolve-dependencies: Avoid code duplication 7216c89: pkgman resolve-dependencies: Improve usage text formatting [ Ingo Weinhold <ingo_weinhold@xxxxxx> ] ---------------------------------------------------------------------------- 6 files changed, 186 insertions(+), 57 deletions(-) headers/os/package/solver/Solver.h | 1 + headers/os/package/solver/SolverRepository.h | 3 +- src/bin/pkgman/command_resolve_dependencies.cpp | 146 +++++++++++++++----- src/kits/package/solver/LibsolvSolver.cpp | 83 ++++++++--- src/kits/package/solver/LibsolvSolver.h | 4 + src/kits/package/solver/SolverRepository.cpp | 6 +- ############################################################################ Commit: 65502bbe88c4686bdefbc5d646b9b681e1c49743 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Wed Apr 3 16:42:20 2013 UTC BSolver: Add VerifyInstallation() ... and implement it in LibsolvSolver. ---------------------------------------------------------------------------- diff --git a/headers/os/package/solver/Solver.h b/headers/os/package/solver/Solver.h index 97cee58..2f1160b 100644 --- a/headers/os/package/solver/Solver.h +++ b/headers/os/package/solver/Solver.h @@ -32,6 +32,7 @@ public: virtual status_t Install( const BSolverPackageSpecifierList& packages) = 0; + virtual status_t VerifyInstallation() = 0; bool HasProblems() const { return CountProblems() > 0; } diff --git a/src/kits/package/solver/LibsolvSolver.cpp b/src/kits/package/solver/LibsolvSolver.cpp index 19aa15b..c12e845 100644 --- a/src/kits/package/solver/LibsolvSolver.cpp +++ b/src/kits/package/solver/LibsolvSolver.cpp @@ -220,32 +220,35 @@ LibsolvSolver::Install(const BSolverPackageSpecifierList& packages) 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; - } + // set jobs' solver mode and solve + _SetJobsSolverMode(jobs, SOLVER_INSTALL); - // 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); + return _Solve(jobs); +} - // 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; - } +status_t +LibsolvSolver::VerifyInstallation() +{ + if (fInstalledRepository == NULL) + return B_BAD_VALUE; - return B_OK; + // add repositories to pool + status_t error = _AddRepositories(); + if (error != B_OK) + return error; + + // prepare pool for solving + pool_createwhatprovides(fPool); + + // add the verify job to the job queue + SolvQueue jobs; + queue_push2(&jobs, SOLVER_SOLVABLE_ALL, 0); + + // set jobs' solver mode and solve + _SetJobsSolverMode(jobs, SOLVER_VERIFY); + + return _Solve(jobs); } @@ -617,3 +620,39 @@ LibsolvSolver::_GetResolvableExpression(Id id, _expression.SetTo(name, op, version); return B_OK; } + + +status_t +LibsolvSolver::_Solve(Queue& jobs) +{ + // 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); + + int problemCount = solver_solve(fSolver, &jobs); + + // get the problems (if any) + fProblems.MakeEmpty(); + + for (Id problemId = 1; problemId <= problemCount; problemId++) { + status_t error = _AddProblem(problemId); + if (error != B_OK) + return error; + } + + return B_OK; +} + + +void +LibsolvSolver::_SetJobsSolverMode(Queue& jobs, int solverMode) +{ + 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; + } +} diff --git a/src/kits/package/solver/LibsolvSolver.h b/src/kits/package/solver/LibsolvSolver.h index 1f4c301..e31eead 100644 --- a/src/kits/package/solver/LibsolvSolver.h +++ b/src/kits/package/solver/LibsolvSolver.h @@ -36,6 +36,7 @@ public: virtual status_t Install( const BSolverPackageSpecifierList& packages); + virtual status_t VerifyInstallation(); virtual int32 CountProblems() const; virtual BSolverProblem* ProblemAt(int32 index) const; @@ -64,6 +65,9 @@ private: BPackageResolvableExpression& _expression) const; + status_t _Solve(Queue& jobs); + void _SetJobsSolverMode(Queue& jobs, int solverMode); + private: Pool* fPool; Solver* fSolver; ############################################################################ Commit: 749884283a72b650748d830648d31eea78b6b7d3 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Wed Apr 3 16:44:14 2013 UTC pkgman resolve-dependencies: Verify result * Make sure that the computed dependencies don't themselves depend on the specified package. * Print only the actual dependencies, not the specified package. ---------------------------------------------------------------------------- diff --git a/src/bin/pkgman/command_resolve_dependencies.cpp b/src/bin/pkgman/command_resolve_dependencies.cpp index 42f9a80..6542d3c 100644 --- a/src/bin/pkgman/command_resolve_dependencies.cpp +++ b/src/bin/pkgman/command_resolve_dependencies.cpp @@ -196,6 +196,47 @@ private: }; +static void +verify_result(const BSolverResult& result, BSolverPackage* specifiedPackage) +{ + // create the solver + BSolver* solver; + status_t error = BSolver::Create(solver); + if (error != B_OK) + DIE(error, "failed to create solver"); + + // Add an installation repository and add all of the result packages save + // the specified package. + BSolverRepository installation; + RepositoryBuilder installationBuilder(installation, "installation"); + + for (int32 i = 0; const BSolverResultElement* element = result.ElementAt(i); + i++) { + BSolverPackage* package = element->Package(); + if (package != specifiedPackage) + installationBuilder.AddPackage(package->Info()); + } + installationBuilder.AddToSolver(solver, true); + + // resolve + error = solver->VerifyInstallation(); + if (error != B_OK) + DIE(error, "failed to verify computed package dependencies"); + + if (solver->HasProblems()) { + fprintf(stderr, + "Encountered problems verifying computed package dependencies:\n"); + + int32 problemCount = solver->CountProblems(); + for (int32 i = 0; i < problemCount; i++) { + printf(" %" B_PRId32 ": %s\n", i + 1, + solver->ProblemAt(i)->ToString().String()); + } + exit(1); + } +} + + int command_resolve_dependencies(int argc, const char* const* argv) { @@ -266,13 +307,14 @@ command_resolve_dependencies(int argc, const char* const* argv) RepositoryBuilder(dummyRepository, "dummy", "specified package") .AddPackage(packagePath) .AddToSolver(solver); - BSolverPackage* package = dummyRepository.PackageAt(0); + BSolverPackage* specifiedPackage = dummyRepository.PackageAt(0); // resolve BSolverPackageSpecifierList packagesToInstall; if (!packagesToInstall.AppendSpecifier( BSolverPackageSpecifier(&dummyRepository, - BPackageResolvableExpression(package->Info().Name())))) { + BPackageResolvableExpression( + specifiedPackage->Info().Name())))) { DIE(B_NO_MEMORY, "failed to add specified package"); } @@ -297,14 +339,22 @@ command_resolve_dependencies(int argc, const char* const* argv) if (error != B_OK) DIE(error, "failed to resolve package dependencies"); + // Verify that the resolved packages don't depend on the specified package. + verify_result(result, specifiedPackage); + // print packages for (int32 i = 0; const BSolverResultElement* element = result.ElementAt(i); i++) { + BSolverPackage* package = element->Package(); + // TODO: Print the path to the package/package info! + // skip the specified package + if (package == specifiedPackage) + continue; + printf("%s-%s\n", - element->Package()->Info().Name().String(), - element->Package()->Info().Version().ToString().String()); -// TODO: Filter out the given package! + package->Info().Name().String(), + package->Info().Version().ToString().String()); } return 0; ############################################################################ Commit: a8b832bf461cc0a4325302d929067c19f4e7aedf Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Wed Apr 3 17:06:47 2013 UTC BSolverRepository::AddPackage(): Add optional return parameter ... returning the added BSolverPackage object. ---------------------------------------------------------------------------- diff --git a/headers/os/package/solver/SolverRepository.h b/headers/os/package/solver/SolverRepository.h index afca10b..24dc961 100644 --- a/headers/os/package/solver/SolverRepository.h +++ b/headers/os/package/solver/SolverRepository.h @@ -58,7 +58,8 @@ public: int32 CountPackages() const; BSolverPackage* PackageAt(int32 index) const; - status_t AddPackage(const BPackageInfo& info); + status_t AddPackage(const BPackageInfo& info, + BSolverPackage** _package = NULL); status_t AddPackages( BPackageInstallationLocation location); diff --git a/src/kits/package/solver/SolverRepository.cpp b/src/kits/package/solver/SolverRepository.cpp index f10360b..b78cb6d 100644 --- a/src/kits/package/solver/SolverRepository.cpp +++ b/src/kits/package/solver/SolverRepository.cpp @@ -238,7 +238,8 @@ BSolverRepository::PackageAt(int32 index) const status_t -BSolverRepository::AddPackage(const BPackageInfo& info) +BSolverRepository::AddPackage(const BPackageInfo& info, + BSolverPackage** _package = NULL) { BSolverPackage* package = new(std::nothrow) BSolverPackage(this, info); if (package == NULL || !fPackages.AddItem(package)) { @@ -246,6 +247,9 @@ BSolverRepository::AddPackage(const BPackageInfo& info) return B_NO_MEMORY; } + if (_package != NULL) + *_package = package; + return B_OK; } ############################################################################ Commit: 4b8aabfac92bcc9be71cf861df8ec83e1a84d944 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Wed Apr 3 17:09:38 2013 UTC pkgman resolve-dependencies: Print package paths ... instead of package name and version. The command should now work as required by haikuporter. ---------------------------------------------------------------------------- diff --git a/src/bin/pkgman/command_resolve_dependencies.cpp b/src/bin/pkgman/command_resolve_dependencies.cpp index 6542d3c..06d8aa3 100644 --- a/src/bin/pkgman/command_resolve_dependencies.cpp +++ b/src/bin/pkgman/command_resolve_dependencies.cpp @@ -14,6 +14,8 @@ #include <stdlib.h> #include <sys/stat.h> +#include <map> + #include <Entry.h> #include <File.h> #include <Path.h> @@ -32,10 +34,13 @@ #include "pkgman.h" +// TODO: internationalization! + + using namespace BPackageKit; -// TODO: internationalization! +typedef std::map<BSolverPackage*, BString> PackagePathMap; static const char* kCommandUsage = @@ -88,17 +93,24 @@ struct RepositoryBuilder { const BString& errorName = BString()) : fRepository(repository), - fErrorName(errorName.IsEmpty() ? name : errorName) + 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) + const char* packageErrorName = NULL, BSolverPackage** _package = NULL) { - status_t error = fRepository.AddPackage(info); + status_t error = fRepository.AddPackage(info, _package); if (error != B_OK) { DIE(error, "failed to add %s to %s repository", packageErrorName != NULL @@ -109,7 +121,8 @@ struct RepositoryBuilder { return *this; } - RepositoryBuilder& AddPackage(const char* path) + RepositoryBuilder& AddPackage(const char* path, + BSolverPackage** _package = NULL) { // read a package info from the (HPKG or package info) file BPackageInfo packageInfo; @@ -130,7 +143,18 @@ struct RepositoryBuilder { if (error != B_OK) DIE(errno, "failed to read package info from \"%s\"", path); - return AddPackage(packageInfo, 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, @@ -193,6 +217,7 @@ struct RepositoryBuilder { private: BSolverRepository& fRepository; BString fErrorName; + PackagePathMap* fPackagePaths; }; @@ -278,6 +303,7 @@ command_resolve_dependencies(int argc, const char* const* argv) DIE(error, "failed to create solver"); // add repositories + PackagePathMap packagePaths; BObjectList<BSolverRepository> repositories(10, true); int32 repositoryIndex = 0; for (int i = 0; i < repositoryDirectoryCount; i++, repositoryIndex++) { @@ -298,6 +324,7 @@ command_resolve_dependencies(int argc, const char* const* argv) } RepositoryBuilder(*repository, BString("repository") << repositoryIndex) + .SetPackagePathMap(&packagePaths) .AddPackagesDirectory(directoryPath) .AddToSolver(solver); } @@ -345,16 +372,20 @@ command_resolve_dependencies(int argc, const char* const* argv) // print packages for (int32 i = 0; const BSolverResultElement* element = result.ElementAt(i); i++) { - BSolverPackage* package = element->Package(); - -// TODO: Print the path to the package/package info! // skip the specified package + BSolverPackage* package = element->Package(); if (package == specifiedPackage) continue; - printf("%s-%s\n", - package->Info().Name().String(), - package->Info().Version().ToString().String()); + // resolve and print the path + PackagePathMap::const_iterator it = packagePaths.find(package); + if (it == packagePaths.end()) { + DIE(B_ERROR, "ugh, no package %p (%s-%s) not in package path map", + package, package->Info().Name().String(), + package->Info().Version().ToString().String()); + } + + printf("%s\n", it->second.String()); } return 0; ############################################################################ Commit: 046f1c437811594ba60a462b9d4e423f7fac5528 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Wed Apr 3 18:11:11 2013 UTC pkgman resolve-dependencies: Avoid code duplication ---------------------------------------------------------------------------- diff --git a/src/bin/pkgman/command_resolve_dependencies.cpp b/src/bin/pkgman/command_resolve_dependencies.cpp index 06d8aa3..44d8854 100644 --- a/src/bin/pkgman/command_resolve_dependencies.cpp +++ b/src/bin/pkgman/command_resolve_dependencies.cpp @@ -222,6 +222,23 @@ private: static void +check_problems(BSolver* solver, const char* errorContext) +{ + if (solver->HasProblems()) { + fprintf(stderr, + "Encountered problems %s:\n", errorContext); + + int32 problemCount = solver->CountProblems(); + for (int32 i = 0; i < problemCount; i++) { + printf(" %" B_PRId32 ": %s\n", i + 1, + solver->ProblemAt(i)->ToString().String()); + } + exit(1); + } +} + + +static void verify_result(const BSolverResult& result, BSolverPackage* specifiedPackage) { // create the solver @@ -248,17 +265,7 @@ verify_result(const BSolverResult& result, BSolverPackage* specifiedPackage) if (error != B_OK) DIE(error, "failed to verify computed package dependencies"); - if (solver->HasProblems()) { - fprintf(stderr, - "Encountered problems verifying computed package dependencies:\n"); - - int32 problemCount = solver->CountProblems(); - for (int32 i = 0; i < problemCount; i++) { - printf(" %" B_PRId32 ": %s\n", i + 1, - solver->ProblemAt(i)->ToString().String()); - } - exit(1); - } + check_problems(solver, "verifying computed package dependencies"); } @@ -349,17 +356,7 @@ command_resolve_dependencies(int argc, const char* const* argv) if (error != B_OK) DIE(error, "failed to resolve package dependencies"); - if (solver->HasProblems()) { - fprintf(stderr, - "Encountered problems resolving package dependencies:\n"); - - int32 problemCount = solver->CountProblems(); - for (int32 i = 0; i < problemCount; i++) { - printf(" %" B_PRId32 ": %s\n", i + 1, - solver->ProblemAt(i)->ToString().String()); - } - exit(1); - } + check_problems(solver, "resolving package dependencies"); BSolverResult result; error = solver->GetResult(result); ############################################################################ Commit: 7216c8944d01a0800e11a2e9f8d04ef307957f91 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Wed Apr 3 18:14:54 2013 UTC pkgman resolve-dependencies: Improve usage text formatting ---------------------------------------------------------------------------- diff --git a/src/bin/pkgman/command_resolve_dependencies.cpp b/src/bin/pkgman/command_resolve_dependencies.cpp index 44d8854..d71aed6 100644 --- a/src/bin/pkgman/command_resolve_dependencies.cpp +++ b/src/bin/pkgman/command_resolve_dependencies.cpp @@ -48,15 +48,17 @@ static const char* kCommandUsage = "Resolves and lists all packages a given package depends on. Fails, if\n" "not all dependencies could be resolved.\n" "\n" - "<package>\n" - " The HPKG or package info file of the package for which the\n" - " dependencies shall be resolved.\n" - "<repository>\n" - " Path to a directory containing packages from which the package's\n" - " dependencies shall be resolved. Multiple directories can be specified.\n" - "<priority>\n" - " Can follow a <repository> to specify the priority of that repository.\n" - " The default priority is 0.\n" + "Arguments:\n" + " <package>\n" + " The HPKG or package info file of the package for which the\n" + " dependencies shall be resolved.\n" + " <repository>\n" + " Path to a directory containing packages from which the package's\n" + " dependencies shall be resolved. Multiple directories can be\n" + " specified.\n" + " <priority>\n" + " Can follow a <repository> to specify the priority of that\n" + " repository. The default priority is 0.\n" "\n" ;