#############################################################################*/
#include <errno.h>
+#include <stdlib.h>
#include <pakfire/i18n.h>
#include <pakfire/pakfire.h>
return 1;
}
-int pakfire_ui_pick_solution(Pakfire pakfire, struct pakfire_request* request,
- struct pakfire_problem** problems) {
+static int pakfire_ui_enter_number(Pakfire pakfire, const char* question,
+ unsigned int* choice, unsigned int min, unsigned int max) {
// Skip this, if running in non-interactive mode
if (pakfire_has_flag(pakfire, PAKFIRE_FLAGS_NON_INTERACTIVE))
- return 1;
+ return 0;
+
+ char* line = NULL;
+ size_t length = 0;
+ char* remainder = NULL;
+ int r = 1;
+
+ while (1) {
+ // Print question
+ printf("%s ", question);
+
+ // 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(_("Invalid value\n"));
+ }
+
+ERROR:
+ if (line)
+ free(line);
+
+ return r;
+}
+
+static struct pakfire_solution** pakfire_ui_append_solutions(
+ struct pakfire_solution** list, struct pakfire_solution** solutions) {
+ unsigned int existing_length = 0;
+ unsigned int appended_length = 0;
+
+ // Count lengths of list
+ if (list) {
+ for (struct pakfire_solution** solution = list; *solution; solution++)
+ existing_length++;
+ }
+
+ // Count what is to be appended
+ for (struct pakfire_solution** solution = solutions; *solution; solution++)
+ appended_length++;
+
+ // Increase array size
+ list = reallocarray(list, existing_length + appended_length + 1, sizeof(*list));
+ if (!list)
+ return NULL;
+
+ // Append all elements to list
+ for (unsigned int i = 0; i < appended_length; i++)
+ list[existing_length + i] = pakfire_solution_ref(solutions[i]);
+ // Terminate the list
+ list[existing_length + appended_length] = NULL;
+
+ return list;
+}
+
+int pakfire_ui_pick_solution(Pakfire pakfire, struct pakfire_request* request,
+ struct pakfire_problem** problems) {
if (!problems) {
errno = EINVAL;
return 1;
}
+ struct pakfire_solution** all_solutions = NULL;
+ unsigned int num_solutions = 0;
+ struct pakfire_solution** solutions = NULL;
+ int r;
+
// Print a headline
- printf("%s\n\n", _("One or more problems have occurred solving your request:"));
+ printf("%s\n", _("One or more problems have occurred solving your request:"));
// Print all problems
for (struct pakfire_problem** problem = problems; *problem; problem++) {
const char* s = pakfire_problem_to_string(*problem);
- printf(" * %s\n", s);
+ printf(" * %s\n", s);
+
+ // Fetch all solutions to this problem
+ r = pakfire_problem_get_solutions(*problem, &solutions);
+ if (r)
+ goto ERROR;
+
+ // Skip the rest if there are no solutions
+ if (!solutions)
+ continue;
+
+ // Append solutions to list
+ all_solutions = pakfire_ui_append_solutions(all_solutions, solutions);
+ if (!all_solutions)
+ goto ERROR;
+
+ // Show a little headline
+ printf(" %s\n", _("Possible solutions:"));
+
+ // Print solutions
+ for (struct pakfire_solution** solution = solutions; *solution; solution++) {
+ s = pakfire_solution_to_string(*solution);
+ if (!s) {
+ for (struct pakfire_solution** solution = solutions; *solution; solution++)
+ pakfire_solution_unref(*solution);
+ free(solutions);
+ goto ERROR;
+ }
+
+ printf(" [%d] %s\n", ++num_solutions, s);
+ }
+
+ // Empty line
+ printf("\n");
+
+ // Free solutions
+ for (struct pakfire_solution** solution = solutions; *solution; solution++)
+ pakfire_solution_unref(*solution);
+ free(solutions);
+ }
+
+ // Skip this, if running in non-interactive mode
+ if (pakfire_has_flag(pakfire, PAKFIRE_FLAGS_NON_INTERACTIVE)) {
+ r = 1;
+ goto ERROR;
}
- // Empty line
- printf("\n");
+ unsigned int choice = 0;
- // Select nothing
- return 1;
+ // Let the user choose which solution they want
+ r = pakfire_ui_enter_number(pakfire, _("Please select a solution:"),
+ &choice, 1, num_solutions);
+ if (r)
+ goto ERROR;
+
+ // Choice is invalid
+ if (!choice)
+ goto ERROR;
+
+ // Fetch selected solution into the solver
+ r = pakfire_request_take_solution(request, all_solutions[choice - 1]);
+ if (r)
+ goto ERROR;
+
+ // Success
+ r = 0;
+
+ERROR:
+ if (all_solutions) {
+ for (struct pakfire_solution** solution = all_solutions; *solution; solution++)
+ pakfire_solution_unref(*solution);
+ free(all_solutions);
+ }
+
+ return r;
}