#include <stdlib.h>
#include <unistd.h>
+#include <pakfire/i18n.h>
#include <pakfire/pakfire.h>
+#include <pakfire/problem.h>
+#include <pakfire/solution.h>
#include "terminal.h"
return r;
}
+
+static int cli_term_enter_number(const char* question, unsigned int* choice,
+ unsigned int min, unsigned int max) {
+ char* line = NULL;
+ size_t length = 0;
+ char* remainder = NULL;
+ int r = 1;
+
+ while (1) {
+ // Print question
+ printf("%s ", question);
+
+ // Do not wait for any input if the terminal isn't interactive
+ if (!cli_term_is_interactive())
+ break;
+
+ // Wait for the user to enter something
+ ssize_t bytes_read = getline(&line, &length, stdin);
+ if (bytes_read < 0)
+ goto ERROR;
+
+ // Convert input into an integer
+ unsigned long int value = strtoul(line, &remainder, 10);
+
+ // The remainder must point to newline
+ if (!remainder || *remainder != '\n')
+ goto AGAIN;
+
+ // The value must be within bounds
+ if (value < min || value > max)
+ goto AGAIN;
+
+ // Store choice
+ *choice = value;
+ r = 0;
+ break;
+
+AGAIN:
+ printf("%s\n", _("Invalid value"));
+ }
+
+ERROR:
+ if (line)
+ free(line);
+
+ return r;
+}
+
+static int cli_term_print_problem(struct pakfire_problem* problem, unsigned int* num_solutions) {
+ struct pakfire_solution** solutions = NULL;
+
+ // Show what the problem is
+ printf(" * %s\n", pakfire_problem_to_string(problem));
+
+ // Fetch the solutions
+ solutions = pakfire_problem_get_solutions(problem);
+
+ if (solutions) {
+ // Show a little headline
+ printf(" %s\n", _("Possible solutions:"));
+
+ // Show all possible solutions
+ for (struct pakfire_solution** s = solutions; *s; s++) {
+ // Increment the solution counter
+ (*num_solutions)++;
+
+ // Show the solution
+ printf(" [%d] %s\n", *num_solutions, pakfire_solution_to_string(*s));
+ }
+ }
+
+ // Cleanup
+ if (solutions) {
+ for (struct pakfire_solution** s = solutions; *s; s++)
+ pakfire_solution_unref(*s);
+
+ free(solutions);
+ }
+
+ return 0;
+}
+
+static struct pakfire_solution* cli_term_find_solution(
+ struct pakfire_problem** problems, const unsigned int choice) {
+ struct pakfire_solution* selected_solution = NULL;
+ struct pakfire_solution** solutions = NULL;
+ int r;
+
+ // Count solutions
+ unsigned int i = 1;
+
+ for (struct pakfire_problem** problem = problems; *problem; problem++) {
+ // Fetch solutions
+ solutions = pakfire_problem_get_solutions(*problem);
+ if (!solutions)
+ continue;
+
+ for (struct pakfire_solution** solution = solutions; *solution; solution++) {
+ if (choice == i++)
+ selected_solution = pakfire_solution_ref(*solution);
+
+ pakfire_solution_unref(*solution);
+ }
+ free(solutions);
+
+ // If we found a solution, we can skip the rest
+ if (selected_solution)
+ break;
+ }
+
+ return selected_solution;
+}
+
+int cli_term_pick_solution(
+ struct pakfire* pakfire, struct pakfire_transaction* transaction, void* data) {
+ struct pakfire_problem** problems = NULL;
+ struct pakfire_solution* solution = NULL;
+ unsigned int num_solutions = 0;
+ unsigned int choice = 0;
+ int r = 0;
+
+ // Fetch all problems
+ problems = pakfire_transaction_get_problems(transaction);
+ if (!problems)
+ goto ERROR;
+
+ for (;;) {
+ // Reset solutions
+ num_solutions = 0;
+
+ // Print a headline
+ printf("%s\n", _("One or more problems have occurred solving your request:"));
+
+ // Show all problems
+ for (struct pakfire_problem** p = problems; *p; p++) {
+ r = cli_term_print_problem(*p, &num_solutions);
+ if (r)
+ goto ERROR;
+ }
+
+ // Let the user choose which solution they want
+ r = cli_term_enter_number(
+ _("Please select a solution:"), &choice, 1, num_solutions);
+ if (r)
+ goto ERROR;
+
+ // Find the selected solution
+ solution = cli_term_find_solution(problems, choice);
+ if (!solution)
+ goto ERROR;
+
+ // Take the selected solution
+ r = pakfire_transaction_take_solution(transaction, solution);
+ if (r)
+ goto ERROR;
+
+ // Success!
+ r = 0;
+ break;
+ }
+
+ERROR:
+ if (problems) {
+ for (struct pakfire_problem** p = problems; *p; p++)
+ pakfire_problem_unref(*p);
+
+ free(problems);
+ }
+ if (solution)
+ pakfire_solution_unref(solution);
+
+ return r;
+}
#define PAKFIRE_CLI_TERMINAL_H
#include <pakfire/pakfire.h>
+#include <pakfire/transaction.h>
int cli_term_confirm(struct pakfire* pakfire,
void* data, const char* message, const char* question);
+int cli_term_pick_solution(
+ struct pakfire* pakfire, struct pakfire_transaction* transaction, void* data);
+
#endif /* PAKFIRE_CLI_TERMINAL_H */
// Configure callbacks
pakfire_set_confirm_callback(pakfire, cli_term_confirm, NULL);
+ // Configure pick solution callback
+ pakfire_set_pick_solution_callback(pakfire, cli_term_pick_solution, NULL);
+
// Enable repositories
for (unsigned int i = 0; i < config.num_enable_repos; i++)
cli_set_repo_enabled(pakfire, config.enable_repos[i], 1);
#include <pakfire/parser.h>
#include <pakfire/repo.h>
#include <pakfire/repolist.h>
+#include <pakfire/transaction.h>
enum pakfire_flags {
PAKFIRE_FLAGS_OFFLINE = (1 << 0),
struct pakfire* pakfire_ref(struct pakfire* pakfire);
struct pakfire* pakfire_unref(struct pakfire* pakfire);
+// Callbacks
+typedef int (*pakfire_pick_solution_callback)
+ (struct pakfire* pakfire, struct pakfire_transaction* transaction, void* data);
+void pakfire_set_pick_solution_callback(
+ struct pakfire* pakfire, pakfire_pick_solution_callback callback, void* data);
+
const char* pakfire_get_path(struct pakfire* pakfire);
int pakfire_clean(struct pakfire* pakfire, int flags);
int pakfire_is_mountpoint(struct pakfire* pakfire, const char* path);
int pakfire_confirm(struct pakfire* pakfire, const char* message, const char* question);
+int pakfire_pick_solution(struct pakfire* pakfire, struct pakfire_transaction* transaction);
magic_t pakfire_get_magic(struct pakfire* pakfire);
#include <pakfire/pakfire.h>
#include <pakfire/problem.h>
+#include <pakfire/solution.h>
enum pakfire_transaction_flags {
PAKFIRE_TRANSACTION_WITHOUT_RECOMMENDED = 1 << 1,
PAKFIRE_JOB_BEST = 1 << 3,
};
-typedef int (*pakfire_transaction_pick_solution_callback)
- (struct pakfire_transaction* transaction, void* data);
-
int pakfire_transaction_create(struct pakfire_transaction** transaction,
struct pakfire* pakfire, int flags);
struct pakfire_transaction* pakfire_transaction_ref(struct pakfire_transaction* transaction);
struct pakfire_transaction* pakfire_transaction_unref(struct pakfire_transaction* transaction);
-// Callbacks
-void pakfire_transaction_set_status_callback(
- struct pakfire_transaction* transaction, pakfire_status_callback callback, void* data);
-void pakfire_transaction_set_pick_solution_callback(
- struct pakfire_transaction* transaction, pakfire_transaction_pick_solution_callback callback, void* data);
-
int pakfire_transaction_solve(struct pakfire_transaction* transaction, int flags, char** problems);
int pakfire_transaction_request(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);
+int pakfire_transaction_take_solution(
+ struct pakfire_transaction* transaction, struct pakfire_solution* solution);
size_t pakfire_transaction_count(struct pakfire_transaction* transaction);
char* pakfire_transaction_dump(struct pakfire_transaction* transaction, size_t width);
+#if 0
void pakfire_transaction_set_status_callback(
struct pakfire_transaction* transaction, pakfire_status_callback callback, void* data);
+#endif
int pakfire_transaction_run(struct pakfire_transaction* transaction);
#include <solv/solver.h>
#include <pakfire/key.h>
-#include <pakfire/solution.h>
// XXX needs removal
enum pakfire_request_solve_flags {
Solver* pakfire_transaction_get_solver(struct pakfire_transaction* transaction);
-int pakfire_transaction_take_solution(struct pakfire_transaction* transaction,
- struct pakfire_solution* solution);
-
int pakfire_transaction_compose_repo(struct pakfire_transaction* transaction,
struct pakfire_key* key, const char* path);
pakfire_search;
pakfire_set_confirm_callback;
pakfire_set_log_callback;
+ pakfire_set_pick_solution_callback;
pakfire_unref;
pakfire_version_compare;
pakfire_whatprovides;
pakfire_transaction_set_pick_solution_callback;
pakfire_transaction_set_status_callback;
pakfire_transaction_solve;
+ pakfire_transaction_take_solution;
pakfire_transaction_unref;
local:
// Confirm
pakfire_confirm_callback confirm;
void* confirm_data;
+
+ // Pick Solution
+ pakfire_pick_solution_callback pick_solution;
+ void* pick_solution_data;
} callbacks;
// Logging
return NULL;
}
+// Callbacks
+
+PAKFIRE_EXPORT void pakfire_set_pick_solution_callback(struct pakfire* pakfire,
+ pakfire_pick_solution_callback callback, void* data) {
+ pakfire->callbacks.pick_solution = callback;
+ pakfire->callbacks.pick_solution_data = data;
+}
+
+int pakfire_pick_solution(struct pakfire* pakfire, struct pakfire_transaction* transaction) {
+ int r = 1;
+
+ // Call the callback
+ if (pakfire->callbacks.pick_solution)
+ r = pakfire->callbacks.pick_solution(
+ pakfire, transaction, pakfire->callbacks.pick_solution_data);
+
+ return r;
+}
+
int pakfire_has_flag(struct pakfire* pakfire, int flag) {
return pakfire->flags & flag;
}
// Status
pakfire_status_callback status;
void* status_data;
-
- // Pick Solution
- pakfire_transaction_pick_solution_callback pick_solution;
- void* pick_solution_data;
} callbacks;
};
transaction->callbacks.status_data = data;
}
-PAKFIRE_EXPORT void pakfire_transaction_set_pick_solution_callback(
- struct pakfire_transaction* transaction, pakfire_transaction_pick_solution_callback callback, void* data) {
- transaction->callbacks.pick_solution = callback;
- transaction->callbacks.pick_solution_data = data;
-}
-
static int pakfire_transaction_get_progress(struct pakfire_transaction* transaction) {
return transaction->progress * 100 / transaction->num;
}
return transaction->solver;
}
-static int pakfire_transaction_pick_solution(struct pakfire_transaction* transaction) {
- int r = 1;
-
- // Call the callback
- if (transaction->callbacks.pick_solution)
- r = transaction->callbacks.pick_solution(
- transaction, transaction->callbacks.pick_solution_data);
-
- return r;
-}
-
PAKFIRE_EXPORT int pakfire_transaction_solve(struct pakfire_transaction* transaction,
int flags, char** problems) {
char* p = NULL;
}
// Ask the user to pick a solution
- r = pakfire_transaction_pick_solution(transaction);
+ r = pakfire_pick_solution(transaction->pakfire, transaction);
switch (r) {
case 0:
goto RETRY;
return __pakfire_transaction_add(transaction, action, SOLVER_SOLVABLE, id, flags);
}
-int pakfire_transaction_take_solution(struct pakfire_transaction* transaction,
+PAKFIRE_EXPORT int pakfire_transaction_take_solution(struct pakfire_transaction* transaction,
struct pakfire_solution* solution) {
struct pakfire_problem* problem = pakfire_solution_get_problem(solution);