]> git.ipfire.org Git - pakfire.git/commitdiff
installcheck: Add a function that checks whether a package can be installed
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 8 May 2023 13:55:19 +0000 (13:55 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 8 May 2023 13:55:19 +0000 (13:55 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/_pakfire/package.c
src/libpakfire/build.c
src/libpakfire/include/pakfire/package.h
src/libpakfire/include/pakfire/request.h
src/libpakfire/libpakfire.sym
src/libpakfire/package.c
src/libpakfire/pakfire.c
src/libpakfire/request.c

index 1e7f48efb5f56888519251f939698df953fee070..0cc17b32422dc8c43126b0a6c425fd5c91077a20 100644 (file)
@@ -28,6 +28,7 @@
 #include <pakfire/repo.h>
 #include <pakfire/util.h>
 
+#include "errors.h"
 #include "package.h"
 #include "pakfire.h"
 #include "repo.h"
@@ -730,6 +731,30 @@ static PyObject* Package_set_source_arch(PackageObject* self, PyObject* value) {
        Py_RETURN_NONE;
 }
 
+static PyObject* Package_installcheck(PackageObject* self) {
+       char* problem = NULL;
+       int r;
+
+       // Perform the installcheck
+       r = pakfire_package_installcheck(self->package, &problem);
+
+       // Success!
+       if (r == 0)
+               Py_RETURN_NONE;
+
+       // We did not get the problem
+       else if (!problem) {
+               PyErr_SetFromErrno(PyExc_OSError);
+
+       // Otherwise raise a dependency error
+       } else {
+               PyErr_SetString(PyExc_DependencyError, problem);
+               free(problem);
+       }
+
+       return NULL;
+}
+
 static struct PyMethodDef Package_methods[] = {
        {
                "dump",
@@ -737,6 +762,12 @@ static struct PyMethodDef Package_methods[] = {
                METH_VARARGS|METH_KEYWORDS,
                NULL,
        },
+       {
+               "installcheck",
+               (PyCFunction)Package_installcheck,
+               METH_NOARGS,
+               NULL,
+       },
        { NULL },
 };
 
index f0245f2f62edb1538c10ad0bf3dcd1e29fb49529..3b9117ab1f41b92249b759ab89f9296f28824d43 100644 (file)
@@ -1882,7 +1882,7 @@ static int pakfire_build_install_test(struct pakfire_build* build) {
        r = pakfire_packagelist_walk(build->packages, pakfire_build_install_package, request);
 
        // Solve the request
-       r = pakfire_request_solve(request);
+       r = pakfire_request_solve(request, 0);
        switch (r) {
                // All okay
                case 0:
@@ -2068,7 +2068,7 @@ static int pakfire_build_install_source_package(
        }
 
        // Solve the request
-       r = pakfire_request_solve(request);
+       r = pakfire_request_solve(request, 0);
        if (r)
                goto ERROR;
 
index a24c84876d09ff9fd80050332a1e16ec4a00c62e..64074fdf69b175dc1cc18b18dd4cd85c0a761a15 100644 (file)
@@ -132,6 +132,9 @@ enum pakfire_package_dump_flags {
        PAKFIRE_PKG_DUMP_LONG     = 1 << 1,
 };
 
+// Installcheck
+int pakfire_package_installcheck(struct pakfire_package* pkg, char** problem);
+
 #ifdef PAKFIRE_PRIVATE
 
 #include <stdint.h>
index 89b808cbd15d1e3ac20d019776f87f95795a7aca..2a206a266fe411ec1f5e83de0abafbdc583ca2d0 100644 (file)
@@ -54,12 +54,16 @@ enum pakfire_request_action {
        PAKFIRE_REQ_VERIFY,
 };
 
+enum pakfire_request_solve_flags {
+       PAKFIRE_REQ_SOLVE_INTERACTIVE,
+};
+
 int pakfire_request_create(struct pakfire_request** request, struct pakfire* pakfire, int flags);
 
 struct pakfire_request* pakfire_request_ref(struct pakfire_request* request);
 struct pakfire_request* pakfire_request_unref(struct pakfire_request* request);
 
-int pakfire_request_solve(struct pakfire_request* request);
+int pakfire_request_solve(struct pakfire_request* request, int flags);
 
 int pakfire_request_add(struct pakfire_request* request,
        const enum pakfire_request_action action, const char* what, int flags);
@@ -71,6 +75,8 @@ int pakfire_request_take_solution(struct pakfire_request* request,
 
 Solver* pakfire_request_get_solver(struct pakfire_request* request);
 
+char* pakfire_request_get_problem_string(struct pakfire_request* request);
+
 int pakfire_request_next_problem(
        struct pakfire_request* request, struct pakfire_problem** problem);
 
index 7378b053c394c1dfab0d61207a84f3a3ba3f19b3..619de92a848b97a3266fe188cf7f3bd0cdc072e1 100644 (file)
@@ -187,6 +187,7 @@ global:
        pakfire_package_get_string;
        pakfire_package_get_uuid;
        pakfire_package_id;
+       pakfire_package_installcheck;
        pakfire_package_ref;
        pakfire_package_set_checksum;
        pakfire_package_set_filelist;
index 363f17c32c5fe92bfc73d00a0e946654600e62ea..7f4bdfd629ba453c7c0102e9221eee0c3d59669f 100644 (file)
@@ -44,6 +44,7 @@
 #include <pakfire/pakfire.h>
 #include <pakfire/private.h>
 #include <pakfire/repo.h>
+#include <pakfire/request.h>
 #include <pakfire/string.h>
 #include <pakfire/util.h>
 
@@ -2057,3 +2058,39 @@ ERROR:
 
        return md;
 }
+
+PAKFIRE_EXPORT int pakfire_package_installcheck(struct pakfire_package* pkg, char** problem) {
+       struct pakfire_request* request = NULL;
+       int r;
+
+       const char* nevra = pakfire_package_get_string(pkg, PAKFIRE_PKG_NEVRA);
+
+       // Create a new request
+       r = pakfire_request_create(&request, pkg->pakfire, 0);
+       if (r)
+               goto ERROR;
+
+       // Install the package
+       r = pakfire_request_add_package(request, PAKFIRE_REQ_INSTALL, pkg, 0);
+       if (r) {
+               ERROR(pkg->pakfire, "Could not add package %s to the request\n", nevra);
+               goto ERROR;
+       }
+
+       // Solve the request
+       r = pakfire_request_solve(request, 0);
+       if (r) {
+               DEBUG(pkg->pakfire, "Could not install %s:\n", nevra);
+
+               // Fetch the problem
+               *problem = pakfire_request_get_problem_string(request);
+               if (*problem)
+                       DEBUG(pkg->pakfire, "%s\n", *problem);
+       }
+
+ERROR:
+       if (request)
+               pakfire_request_unref(request);
+
+       return r;
+}
index 5809de3443985d04b6a2481e2f67b1f27c32020f..4f28310a6697d517cb4dcd2cee636dcf20d4c2bc 100644 (file)
@@ -1950,7 +1950,7 @@ static int pakfire_perform_transaction(
        }
 
        // Solve the request
-       r = pakfire_request_solve(request);
+       r = pakfire_request_solve(request, PAKFIRE_REQ_SOLVE_INTERACTIVE);
        if (r)
                goto ERROR;
 
@@ -2057,7 +2057,7 @@ static int pakfire_perform_transaction_simple(struct pakfire* pakfire, int solve
                goto ERROR;
 
        // Solve the request
-       r = pakfire_request_solve(request);
+       r = pakfire_request_solve(request, PAKFIRE_REQ_SOLVE_INTERACTIVE);
        if (r)
                goto ERROR;
 
index 99a42b37750de805ec25aba326601c8f82b01e8f..d9b15d98d97e6a2ba0e7b62dab4b76fc1b4535b4 100644 (file)
@@ -51,9 +51,6 @@ struct pakfire_request {
 
        Solver* solver;
        Queue jobs;
-
-       // Set if the request has been solved
-       int solved:1;
 };
 
 static void pakfire_request_free(struct pakfire_request* request) {
@@ -173,7 +170,8 @@ static int pakfire_request_pick_solution(struct pakfire_request* request) {
        return pakfire_ui_pick_solution(request->pakfire, request);
 }
 
-int pakfire_request_solve(struct pakfire_request* request) {
+int pakfire_request_solve(struct pakfire_request* request, int flags) {
+       int solved = 0;
        int r;
 
        // Prepare pool
@@ -191,26 +189,33 @@ int pakfire_request_solve(struct pakfire_request* request) {
        // Save time when we starting solving
        clock_t solving_start = clock();
 
-       for (;;) {
-               r = solver_solve(request->solver, &request->jobs);
-               if (r == 0)
+RETRY:
+       r = solver_solve(request->solver, &request->jobs);
+       switch (r) {
+               // Solved!
+               case 0:
+                       // Mark as solved
+                       solved = 1;
                        break;
 
-               // We land here, if the request could not be solved
-
+               // Not Solved
+               default:
 #ifdef ENABLE_DEBUG
-               // Print all solutions
-               solver_printallsolutions(request->solver);
+                       // Print all solutions
+                       solver_printallsolutions(request->solver);
 #endif
 
-               // Ask the user to pick a solution
-               r = pakfire_request_pick_solution(request);
-               if (r)
-                       return r;
-       }
+                       // Ask the user to pick a solution
+                       if (flags & PAKFIRE_REQ_SOLVE_INTERACTIVE) {
+                               r = pakfire_request_pick_solution(request);
+                               if (r)
+                                       return r;
 
-       // Mark the request as solved
-       request->solved = 1;
+                               // Retry solving
+                               goto RETRY;
+                       }
+                       break;
+       }
 
        // Save time when we finished solving
        clock_t solving_end = clock();
@@ -219,11 +224,15 @@ int pakfire_request_solve(struct pakfire_request* request) {
                (double)(solving_end - solving_start) * 1000 / CLOCKS_PER_SEC);
 
 #ifdef ENABLE_DEBUG
-       solver_printdecisions(request->solver);
+       if (solved)
+               solver_printdecisions(request->solver);
 #endif
 
-       // All okay
-       return 0;
+       // Return zero if solved, otherwise return non-zero
+       if (solved)
+               return 0;
+
+       return 2;
 }
 
 static int pakfire_request_is_file(const char* what) {
@@ -401,6 +410,26 @@ int pakfire_request_add_package(struct pakfire_request* request,
        return __pakfire_request_add(request, action, SOLVER_SOLVABLE, id, flags);
 }
 
+char* pakfire_request_get_problem_string(struct pakfire_request* request) {
+       struct pakfire_problem* problem = NULL;
+       char* s = NULL;
+       int r;
+
+       for (;;) {
+               r = pakfire_request_next_problem(request, &problem);
+               if (r || !problem)
+                       break;
+
+               const char* p = pakfire_problem_to_string(problem);
+
+               r = asprintf(&s, "%s%s\n", (s) ? s : "", p);
+               if (r < 0)
+                       return NULL;
+       }
+
+       return s;
+}
+
 int pakfire_request_next_problem(
                struct pakfire_request* request, struct pakfire_problem** problem) {
        Id id = 0;