}
static PyObject* Problem_get_solutions(ProblemObject* self) {
- struct pakfire_solution* solution = NULL;
- PyObject* solution_obj = NULL;
+ struct pakfire_solution** solutions = NULL;
+ PyObject* s = NULL;
int r;
PyObject* list = PyList_New(0);
if (!list)
return NULL;
- for (;;) {
- r = pakfire_problem_next_solution(self->problem, &solution);
- if (r)
- goto ERROR;
+ // Fetch any solutions
+ solutions = pakfire_problem_get_solutions(self->problem);
- // No more solutions
- if (!solution)
- break;
+ if (solutions) {
+ for (struct pakfire_solution** solution = solutions; *solution; solution++) {
+ s = new_solution(*solution);
+ if (!s)
+ goto ERROR;
- // Create a new Solution object
- solution_obj = new_solution(solution);
- if (!solution_obj) {
- pakfire_solution_unref(solution);
- goto ERROR;
+ // Append the solution to the list
+ r = PyList_Append(list, s);
+ Py_DECREF(s);
+ if (r)
+ goto ERROR;
}
- // Append the solution to the list
- r = PyList_Append(list, solution_obj);
- if (r) {
- pakfire_solution_unref(solution);
- goto ERROR;
- }
-
- Py_DECREF(solution_obj);
+ // Cleanup
+ for (struct pakfire_solution** solution = solutions; *solution; solution++)
+ pakfire_solution_unref(*solution);
+ free(solutions);
}
return list;
ERROR:
+ if (solutions) {
+ for (struct pakfire_solution** solution = solutions; *solution; solution++)
+ pakfire_solution_unref(*solution);
+ free(solutions);
+ }
+
Py_DECREF(list);
+
return NULL;
}
static int pakfire_build_install_test(struct pakfire_build* build) {
struct pakfire_transaction* transaction = NULL;
- struct pakfire_problem* problem = NULL;
- struct pakfire_solution* solution = NULL;
- const char* s = NULL;
+ char* problems = NULL;
int r;
// Create a new transaction
r = pakfire_packagelist_walk(build->packages, pakfire_build_install_package, transaction);
// Solve the request
- r = pakfire_transaction_solve(transaction, 0, NULL);
+ r = pakfire_transaction_solve(transaction, PAKFIRE_SOLVE_SHOW_SOLUTIONS, &problems);
switch (r) {
// All okay
case 0:
// Dependency Error
case 2:
- ERROR(build->pakfire, "Install test failed:\n");
-
- // Walk through all problems
- for (;;) {
- r = pakfire_transaction_next_problem(transaction, &problem);
- if (r)
- goto ERROR;
-
- // There are no more problems
- if (!problem)
- break;
-
- // Format the problem into something human-readable
- s = pakfire_problem_to_string(problem);
- if (!s)
- continue;
-
- ERROR(build->pakfire, " * %s\n", s);
-
- // Walk through all solutions
- for (;;) {
- r = pakfire_problem_next_solution(problem, &solution);
- if (r)
- goto ERROR;
-
- // There are no more solutions
- if (!solution)
- break;
-
- // Format the solution into something human-readable
- s = pakfire_solution_to_string(solution);
- if (!s)
- continue;
-
- ERROR(build->pakfire, " * %s\n", s);
- }
- }
-
+ ERROR(build->pakfire, "Install test failed:\n%s\n", problems);
break;
// Any other errors
default:
+ ERROR(build->pakfire, "Install test failed: %m\n");
goto ERROR;
}
ERROR:
- if (r)
- ERROR(build->pakfire, "Install test failed: %m\n");
- if (problem)
- pakfire_problem_unref(problem);
- if (solution)
- pakfire_solution_unref(solution);
+ if (problems)
+ free(problems);
return r;
}
const char* pakfire_problem_to_string(struct pakfire_problem* problem);
-int pakfire_problem_next_solution(
- struct pakfire_problem* problem, struct pakfire_solution** solution);
+struct pakfire_solution** pakfire_problem_get_solutions(
+ struct pakfire_problem* problem);
#ifdef PAKFIRE_PRIVATE
+#include <solv/pooltypes.h>
+
#include <pakfire/transaction.h>
int pakfire_problem_create(struct pakfire_problem** problem, struct pakfire* pakfire,
struct pakfire_solution;
+#include <pakfire/pakfire.h>
#include <pakfire/problem.h>
struct pakfire_solution* pakfire_solution_ref(struct pakfire_solution* solution);
#ifdef PAKFIRE_PRIVATE
+#include <solv/pooltypes.h>
-int pakfire_solution_create(struct pakfire_solution** solution,
+int pakfire_solution_create(struct pakfire_solution** solution, struct pakfire* pakfire,
struct pakfire_problem* problem, Id id);
struct pakfire_problem* pakfire_solution_get_problem(struct pakfire_solution* solution);
Id pakfire_solution_get_id(struct pakfire_solution* solution);
PAKFIRE_TRANSACTION_ALLOW_DOWNGRADE = 1 << 3,
};
+enum pakfire_transaction_solve_flags {
+ PAKFIRE_SOLVE_SHOW_SOLUTIONS = 1 << 0,
+};
+
enum pakfire_job_action {
PAKFIRE_JOB_INSTALL,
PAKFIRE_JOB_ERASE,
int pakfire_transaction_request_package(struct pakfire_transaction* transaction,
const enum pakfire_job_action action, struct pakfire_package* package, int flags);
+struct pakfire_problem** pakfire_transaction_get_problems(struct pakfire_transaction* transaction);
+
size_t pakfire_transaction_count(struct pakfire_transaction* transaction);
char* pakfire_transaction_dump(struct pakfire_transaction* transaction, size_t width);
Solver* pakfire_transaction_get_solver(struct pakfire_transaction* transaction);
-int pakfire_transaction_next_problem(
- struct pakfire_transaction* transaction, struct pakfire_problem** problem);
-
int pakfire_transaction_take_solution(struct pakfire_transaction* transaction,
struct pakfire_solution* solution);
pakfire_packagelist_unref;
# problem
- pakfire_problem_next_solution;
+ pakfire_problem_get_solutions;
pakfire_problem_ref;
pakfire_problem_to_string;
pakfire_problem_unref;
pakfire_transaction_create;
pakfire_transaction_download;
pakfire_transaction_dump;
+ pakfire_transaction_get_problems;
pakfire_transaction_ref;
pakfire_transaction_request;
pakfire_transaction_request_package;
struct pakfire_transaction* transaction;
Id id;
char* string;
+
+ Solver* solver;
};
static char* pakfire_problem_make_string(struct pakfire_problem* problem) {
p->transaction = pakfire_transaction_ref(transaction);
p->id = id;
+ // Fetch a reference to the solver
+ p->solver = pakfire_transaction_get_solver(transaction);
+
*problem = p;
return 0;
}
return pakfire_transaction_ref(problem->transaction);
}
-PAKFIRE_EXPORT int pakfire_problem_next_solution(
- struct pakfire_problem* problem, struct pakfire_solution** solution) {
- Solver* solver = pakfire_transaction_get_solver(problem->transaction);
- Id id = 0;
+PAKFIRE_EXPORT struct pakfire_solution** pakfire_problem_get_solutions(
+ struct pakfire_problem* problem) {
+ struct pakfire_solution** solutions = NULL;
+ struct pakfire_solution* solution = NULL;
+ unsigned int count = 0;
+ Id id = ID_NULL;
+ int r;
+
+ // Fetch how many solutions we have
+ count = solver_solution_count(problem->solver, problem->id);
+ if (!count)
+ return NULL;
- // Check input
- if (!solution) {
- errno = EINVAL;
- return 1;
+ // Allocate some space
+ solutions = calloc(count + 1, sizeof(*solutions));
+ if (!solutions) {
+ r = -errno;
+ goto ERROR;
}
- // Fetch the ID of the previous solution
- if (*solution) {
- id = pakfire_solution_get_id(*solution);
+ for (unsigned int i = 0; i < count; i++) {
+ id = solver_next_solution(problem->solver, problem->id, id);
+ if (!id)
+ break;
+
+ // Create a new solution
+ r = pakfire_solution_create(&solution, problem->pakfire, problem, id);
+ if (r)
+ goto ERROR;
- // Free the previous solution
- pakfire_solution_unref(*solution);
- *solution = NULL;
+ // Store the reference
+ solutions[i] = solution;
}
- // Fetch the ID of the next problem
- id = solver_next_solution(solver, problem->id, id);
- if (!id)
- return 0;
+ return solutions;
+
+ERROR:
+ ERROR_ERRNO(problem->pakfire, r, "Could not import solutions: %m\n");
+
+ if (solutions) {
+ for (struct pakfire_solution** s = solutions; *s; s++)
+ pakfire_solution_unref(*s);
- // Create solution
- return pakfire_solution_create(solution, problem, id);
+ free(solutions);
+ }
+
+ return NULL;
}
# #
#############################################################################*/
+#include <errno.h>
#include <stdlib.h>
#include <solv/policy.h>
#include <pakfire/constants.h>
#include <pakfire/i18n.h>
#include <pakfire/logging.h>
+#include <pakfire/pakfire.h>
#include <pakfire/private.h>
#include <pakfire/problem.h>
#include <pakfire/solution.h>
};
int pakfire_solution_create(struct pakfire_solution** solution,
- struct pakfire_problem* problem, Id id) {
+ struct pakfire* pakfire, struct pakfire_problem* problem, Id id) {
struct pakfire_solution* s = calloc(1, sizeof(*s));
if (!s)
- return 1;
+ return -errno;
- s->pakfire = pakfire_problem_get_pakfire(problem);
+ // Store a reference to pakfire
+ s->pakfire = pakfire_ref(pakfire);
+
+ // Initialize the ref counter
s->nrefs = 1;
// Store a reference to the problem
s->problem = pakfire_problem_ref(problem);
+
+ // Store the ID
s->id = id;
*solution = s;
if (transaction->transaction)
transaction_free(transaction->transaction);
-
if (transaction->solver)
solver_free(transaction->solver);
pakfire_unref(transaction->pakfire);
free(buffer);
}
-static char* pakfire_transaction_get_problem_string(struct pakfire_transaction* transaction) {
+PAKFIRE_EXPORT struct pakfire_problem** pakfire_transaction_get_problems(
+ struct pakfire_transaction* transaction) {
+ struct pakfire_problem** problems = NULL;
struct pakfire_problem* problem = NULL;
- const char* p = NULL;
- char* s = NULL;
+ unsigned int count = 0;
+ Id id = ID_NULL;
int r;
- for (;;) {
- r = pakfire_transaction_next_problem(transaction, &problem);
- if (r || !problem)
+ // Count problems
+ count = solver_problem_count(transaction->solver);
+
+ // Return NULL if there are no problems
+ if (!count)
+ return NULL;
+
+ // Allocate some space
+ problems = calloc(count + 1, sizeof(*problems));
+ if (!problems) {
+ r = -errno;
+ goto ERROR;
+ }
+
+ for (unsigned int i = 0; i < count; i++) {
+ // Fetch the ID of the next problem
+ id = solver_next_problem(transaction->solver, id);
+ if (!id)
break;
- p = pakfire_problem_to_string(problem);
- if (!p)
+ // Create a new problem
+ r = pakfire_problem_create(&problem, transaction->pakfire, transaction, id);
+ if (r)
goto ERROR;
- r = asprintf(&s, "%s%s\n", (s) ? s : "", p);
- if (r < 0)
- goto ERROR;
+ // Store the reference
+ problems[i] = problem;
}
- return s;
+ return problems;
ERROR:
- if (s)
- free(s);
+ ERROR_ERRNO(transaction->pakfire, r, "Could not import problems: %m\n");
+
+ if (problems) {
+ for (struct pakfire_problem** p = problems; *p; p++)
+ pakfire_problem_unref(*p);
+ free(problems);
+ }
return NULL;
}
+static int pakfire_transaction_append_solutions(
+ struct pakfire_transaction* transaction, char** buffer, struct pakfire_solution** solutions) {
+ const char* s = NULL;
+ int r;
+
+ for (struct pakfire_solution** solution = solutions; *solution; solution++) {
+ s = pakfire_solution_to_string(*solution);
+ if (!s)
+ return -errno;
+
+ // Append the solution
+ r = asprintf(buffer, "%s - %s\n", *buffer, s);
+ if (r < 0)
+ return -errno;
+ }
+
+ return 0;
+}
+
+static int pakfire_transaction_append_problems(
+ struct pakfire_transaction* transaction, char** buffer, struct pakfire_problem** problems, int flags) {
+ struct pakfire_solution** solutions = NULL;
+ const char* s = NULL;
+ int r;
+
+ for (struct pakfire_problem** problem = problems; *problem; problem++) {
+ s = pakfire_problem_to_string(*problem);
+ if (!s)
+ return -errno;
+
+ // Append the string to the buffer
+ r = asprintf(buffer, "%s* %s\n", *buffer, s);
+ if (r < 0)
+ return -errno;
+
+ // Show solutions
+ if (flags & PAKFIRE_SOLVE_SHOW_SOLUTIONS) {
+ // Fetch any solutions
+ solutions = pakfire_problem_get_solutions(*problem);
+
+ if (solutions) {
+ r = pakfire_transaction_append_solutions(transaction, buffer, solutions);
+
+ // Cleanup
+ for (struct pakfire_solution** solution = solutions; *solution; solution++)
+ pakfire_solution_unref(*solution);
+ free(solutions);
+
+ if (r)
+ return r;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static char* pakfire_transaction_get_problem_string(
+ struct pakfire_transaction* transaction, int flags) {
+ struct pakfire_problem** problems = NULL;
+ char* buffer = "";
+ int r;
+
+ // Fetch any problems
+ problems = pakfire_transaction_get_problems(transaction);
+
+ // Show problems
+ if (problems) {
+ // Append all problems
+ r = pakfire_transaction_append_problems(transaction, &buffer, problems, flags);
+ if (r) {
+ if (buffer)
+ free(buffer);
+
+ buffer = NULL;
+ }
+
+ // Cleanup
+ if (problems) {
+ for (struct pakfire_problem** problem = problems; *problem; problem++)
+ pakfire_problem_unref(*problem);
+
+ free(problems);
+ }
+ }
+
+ return buffer;
+}
+
Solver* pakfire_transaction_get_solver(struct pakfire_transaction* transaction) {
return transaction->solver;
}
// Save time when we starting solving
clock_t solving_start = clock();
+ // Solve the request and get the number of problems
r = solver_solve(transaction->solver, &transaction->jobs);
// Save time when we finished solving
// Return the problems as string
if (problems)
- *problems = pakfire_transaction_get_problem_string(transaction);
+ *problems = pakfire_transaction_get_problem_string(transaction, flags);
// Ask the user to pick a solution
if (flags & PAKFIRE_REQ_SOLVE_INTERACTIVE) {
goto RETRY;
} else {
- char* s = pakfire_transaction_get_problem_string(transaction);
+ char* s = pakfire_transaction_get_problem_string(transaction, 0);
if (s)
ERROR(transaction->pakfire, "%s\n", s);
}
return __pakfire_transaction_add(transaction, action, SOLVER_SOLVABLE, id, flags);
}
-int pakfire_transaction_next_problem(
- struct pakfire_transaction* transaction, struct pakfire_problem** problem) {
- Id id = 0;
-
- // Check input
- if (!problem) {
- errno = EINVAL;
- return 1;
- }
-
- // Fetch the ID of the previous problem
- if (*problem) {
- id = pakfire_problem_get_id(*problem);
-
- // Free the previous problem
- pakfire_problem_unref(*problem);
- *problem = NULL;
- }
-
- // Fetch the ID of the next problem
- id = solver_next_problem(transaction->solver, id);
- if (!id)
- return 0;
-
- // Create problem
- return pakfire_problem_create(problem, transaction->pakfire, transaction, id);
-}
-
int pakfire_transaction_take_solution(struct pakfire_transaction* transaction,
struct pakfire_solution* solution) {
struct pakfire_problem* problem = pakfire_solution_get_problem(solution);
}
int pakfire_ui_pick_solution(struct pakfire* pakfire, struct pakfire_transaction* transaction) {
+#if 0
struct pakfire_problem* problem = NULL;
struct pakfire_solution** solutions = NULL;
struct pakfire_solution* solution = NULL;
}
return r;
+#endif
+
+ return 0;
}