]> git.ipfire.org Git - pakfire.git/commitdiff
transactions: Refactor dumping transactions & steps
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 27 Apr 2021 16:41:04 +0000 (16:41 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 27 Apr 2021 16:41:04 +0000 (16:41 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/include/pakfire/step.h
src/libpakfire/include/pakfire/transaction.h
src/libpakfire/request.c
src/libpakfire/step.c
src/libpakfire/transaction.c

index bc588d5b33acd592ee5d47998c8c28b0aef64365..f8bb59ff052d92a1d805bc1671f7d3a6c2c9c443 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <pakfire/types.h>
 
-PakfireStep pakfire_step_create(PakfireTransaction transaction,
+int pakfire_step_create(PakfireStep* step, Pakfire pakfire,
        pakfire_step_type_t type, PakfirePackage pkg);
 PakfireStep pakfire_step_ref(PakfireStep step);
 PakfireStep pakfire_step_unref(PakfireStep step);
index 6a182d59182b2f6f41ca13eecaf3b82e8c8681a7..a544a58c70e82d18560ec7795e3924c096115f46 100644 (file)
 #ifndef PAKFIRE_TRANSACTION_H
 #define PAKFIRE_TRANSACTION_H
 
-#include <solv/transaction.h>
-
 #include <pakfire/types.h>
 
-PakfireTransaction pakfire_transaction_create(Pakfire pakfire, Transaction* trans);
 PakfireTransaction pakfire_transaction_ref(PakfireTransaction transaction);
 PakfireTransaction pakfire_transaction_unref(PakfireTransaction transaction);
 
@@ -45,7 +42,9 @@ int pakfire_transaction_download(PakfireTransaction transaction);
 
 #ifdef PAKFIRE_PRIVATE
 
-Transaction* pakfire_transaction_get_transaction(PakfireTransaction transaction);
+#include <solv/transaction.h>
+
+int pakfire_transaction_create(PakfireTransaction* transaction, Pakfire pakfire, Transaction* trans);
 
 #endif
 
index 83f024b508791457c5469d24639f272fc15b1655..38d95ac02fbd074db32bd65ac82363e674b074cb 100644 (file)
@@ -227,7 +227,12 @@ PAKFIRE_EXPORT PakfireTransaction pakfire_request_get_transaction(struct pakfire
        if (!request->transaction)
                return NULL;
 
-       return pakfire_transaction_create(request->pakfire, request->transaction);
+       PakfireTransaction transaction;
+       int r = pakfire_transaction_create(&transaction, request->pakfire, request->transaction);
+       if (r)
+               return NULL;
+
+       return transaction;
 }
 
 static int pakfire_request_is_file(const char* what) {
index 764ca040e7279e6de821a35021357bca0041f003..8dfdef6aa44314fc1d65969ab30d7c4bae088d95 100644 (file)
@@ -49,24 +49,26 @@ struct _PakfireStep {
        int nrefs;
 };
 
-PAKFIRE_EXPORT PakfireStep pakfire_step_create(PakfireTransaction transaction,
+PAKFIRE_EXPORT int pakfire_step_create(PakfireStep* step, Pakfire pakfire,
                pakfire_step_type_t type, PakfirePackage pkg) {
-       Pakfire pakfire = pakfire_transaction_get_pakfire(transaction);
+       PakfireStep s = calloc(1, sizeof(*s));
+       if (!s)
+               return ENOMEM;
 
-       PakfireStep step = calloc(1, sizeof(*step));
-       if (step) {
-               DEBUG(pakfire, "Allocated Step at %p\n", step);
-               step->pakfire = pakfire_ref(pakfire);
-               step->nrefs = 1;
+       // Store a reference to Pakfire
+       s->pakfire = pakfire_ref(pakfire);
 
-               // Save everything
-               step->type = type;
-               step->package = pakfire_package_ref(pkg);
-       }
+       // Initialize the reference counter
+       s->nrefs = 1;
 
-       pakfire_unref(pakfire);
+       // Store a reference to the package
+       s->package = pakfire_package_ref(pkg);
 
-       return step;
+       // Store type
+       s->type = type;
+
+       *step = s;
+       return 0;
 }
 
 PAKFIRE_EXPORT PakfireStep pakfire_step_ref(PakfireStep step) {
@@ -86,9 +88,6 @@ static void pakfire_step_free(PakfireStep step) {
 }
 
 PAKFIRE_EXPORT PakfireStep pakfire_step_unref(PakfireStep step) {
-       if (!step)
-               return NULL;
-
        if (--step->nrefs > 0)
                return step;
 
index 9b8d57ffddba46e66efbaf3c040cf9d4626ecdf8..7e01b48eb09f08df584014dbcd28d60d4c42ed1e 100644 (file)
 
 struct _PakfireTransaction {
        Pakfire pakfire;
+       int nrefs;
+
        Transaction* transaction;
+
        PakfireStep* steps;
        size_t num_steps;
-       int nrefs;
 };
 
-static pakfire_step_type_t transaction_get_step_type(Transaction* transaction, Id id) {
-       int type = transaction_type(transaction, id,
-               SOLVER_TRANSACTION_SHOW_ACTIVE|SOLVER_TRANSACTION_CHANGE_IS_REINSTALL);
+static pakfire_step_type_t transaction_get_step_type(PakfireTransaction transaction, Id id) {
+       int type = transaction_type(transaction->transaction, id, 0);
 
        // Translate solver types into our own types
        switch (type) {
@@ -80,63 +81,94 @@ static pakfire_step_type_t transaction_get_step_type(Transaction* transaction, I
        }
 }
 
-PAKFIRE_EXPORT PakfireTransaction pakfire_transaction_create(Pakfire pakfire, Transaction* trans) {
-       PakfireTransaction transaction = calloc(1, sizeof(*transaction));
-       if (transaction) {
-               DEBUG(pakfire, "Allocated Transaction at %p\n", transaction);
-               transaction->nrefs = 1;
+static void pakfire_transaction_free(PakfireTransaction transaction) {
+       // Release all steps
+       if (transaction->steps) {
+               for (unsigned int i = 0; i < transaction->num_steps; i++)
+                       pakfire_step_unref(transaction->steps[i]);
+               free(transaction->steps);
+       }
 
-               transaction->pakfire = pakfire_ref(pakfire);
+       transaction_free(transaction->transaction);
 
-               // Clone the transaction, so we get independent from what ever called this.
-               if (trans) {
-                       transaction->transaction = transaction_create_clone(trans);
-                       transaction_order(transaction->transaction, 0);
-               } else {
-                       transaction->transaction = transaction_create(trans->pool);
-               }
+       pakfire_unref(transaction->pakfire);
+       free(transaction);
+}
 
-               // Save total number of steps
-               transaction->num_steps = transaction->transaction->steps.count;
+static int pakfire_transaction_add_step(PakfireTransaction transaction, Id id) {
+       int type = transaction_get_step_type(transaction, id);
 
-               // Import all steps
-               PakfireStep* steps = transaction->steps = calloc(transaction->num_steps + 1, sizeof(*steps));
-               for (unsigned int i = 0; i < transaction->num_steps; i++) {
-                       Id id = transaction->transaction->steps.elements[i];
+       // Do not add ignored steps
+       if (type == PAKFIRE_STEP_IGNORE)
+               return 0;
 
-                       // Get the type
-                       pakfire_step_type_t type = transaction_get_step_type(transaction->transaction, id);
+       // Allocate more space
+       transaction->steps = reallocarray(transaction->steps, sizeof(*transaction->steps),
+               transaction->num_steps + 1);
+       if (!transaction->steps)
+               return 1;
 
-                       // Fetch the package
-                       PakfirePackage pkg = pakfire_package_create_from_solvable(pakfire, id);
+       PakfirePackage pkg = pakfire_package_create_from_solvable(transaction->pakfire, id);
+       if (!pkg)
+               return 1;
 
-                       // Append a new step
-                       *steps++ = pakfire_step_create(transaction, type, pkg);
+       PakfireStep step;
+       int r = pakfire_step_create(&step, transaction->pakfire, type, pkg);
+       if (r)
+               goto ERROR;
 
-                       pakfire_package_unref(pkg);
-               }
-       }
+       transaction->steps[transaction->num_steps++] = step;
 
-       return transaction;
-}
+       // Success
+       r = 0;
 
-PAKFIRE_EXPORT PakfireTransaction pakfire_transaction_ref(PakfireTransaction transaction) {
-       transaction->nrefs++;
+ERROR:
+       if (pkg)
+               pakfire_package_unref(pkg);
 
-       return transaction;
+       return r;
 }
 
-void pakfire_transaction_free(PakfireTransaction transaction) {
-       DEBUG(transaction->pakfire, "Releasing Transaction at %p\n", transaction);
+int pakfire_transaction_create(PakfireTransaction* transaction,
+               Pakfire pakfire, Transaction* trans) {
+       PakfireTransaction t = calloc(1, sizeof(*t));
+       if (!t)
+               return ENOMEM;
 
-       // Release all steps
-       while (*transaction->steps)
-               pakfire_step_unref(*transaction->steps++);
+       // Store reference to Pakfire
+       t->pakfire = pakfire_ref(pakfire);
 
-       transaction_free(transaction->transaction);
+       // Initialize the reference counter
+       t->nrefs = 1;
 
-       pakfire_unref(transaction->pakfire);
-       free(transaction);
+       // Clone the transaction to keep a copy of it
+       t->transaction = transaction_create_clone(trans);
+       if (!t->transaction)
+               goto ERROR;
+
+       // Order the transaction
+       transaction_order(t->transaction, 0);
+
+       // Import steps
+       for (int i = 0; i < t->transaction->steps.count; i++) {
+               int r = pakfire_transaction_add_step(t, t->transaction->steps.elements[i]);
+               if (r)
+                       goto ERROR;
+       }
+
+       *transaction = t;
+       return 0;
+
+ERROR:
+       pakfire_transaction_free(t);
+
+       return 1;
+}
+
+PAKFIRE_EXPORT PakfireTransaction pakfire_transaction_ref(PakfireTransaction transaction) {
+       transaction->nrefs++;
+
+       return transaction;
 }
 
 PAKFIRE_EXPORT PakfireTransaction pakfire_transaction_unref(PakfireTransaction transaction) {
@@ -151,10 +183,6 @@ PAKFIRE_EXPORT Pakfire pakfire_transaction_get_pakfire(PakfireTransaction transa
        return pakfire_ref(transaction->pakfire);
 }
 
-Transaction* pakfire_transaction_get_transaction(PakfireTransaction transaction) {
-       return transaction->transaction;
-}
-
 PAKFIRE_EXPORT size_t pakfire_transaction_count(PakfireTransaction transaction) {
        return transaction->num_steps;
 }
@@ -169,8 +197,8 @@ PAKFIRE_EXPORT ssize_t pakfire_transaction_installsizechange(PakfireTransaction
 PAKFIRE_EXPORT ssize_t pakfire_transaction_downloadsize(PakfireTransaction transaction) {
        ssize_t size = 0;
 
-       for (PakfireStep* step = transaction->steps; *step; step++)
-               size += pakfire_step_get_downloadsize(*step);
+       for (unsigned int i = 0; i < transaction->num_steps; i++)
+               size += pakfire_step_get_downloadsize(transaction->steps[i]);
 
        return size;
 }
@@ -235,6 +263,14 @@ static void pakfire_transaction_add_package(char** str, size_t width, PakfirePac
        pakfire_repo_unref(repo);
 }
 
+static void pakfire_transaction_add_package_change(char** str, size_t width,
+               PakfirePackage pkg1, PakfirePackage pkg2) {
+       // Print the new package first
+       pakfire_transaction_add_package(str, width, pkg1);
+
+       asprintf(str, "%s   --> %s\n", *str, pakfire_package_get_nevra(pkg2));
+}
+
 static void pakfire_transaction_add_separator(char** str, size_t width) {
        while (width-- > 0)
                asprintf(str, "%s=", *str);
@@ -243,39 +279,6 @@ static void pakfire_transaction_add_separator(char** str, size_t width) {
        asprintf(str, "%s\n", *str);
 }
 
-static size_t pakfire_transaction_add_section(char** str, size_t width, PakfireTransaction transaction,
-               const char* headline, pakfire_step_type_t type) {
-       PakfirePackageList list = pakfire_transaction_get_packages(transaction, type);
-
-       // Nothing to do if there are no packages in this stage
-       size_t c = pakfire_packagelist_count(list);
-       if (c == 0)
-               goto END;
-
-       // Headline
-       pakfire_transaction_add_headline(str, width, headline);
-
-       // List each package
-       for (unsigned int i = 0; i < c; i++) {
-               PakfirePackage pkg = pakfire_packagelist_get(list, i);
-               pakfire_transaction_add_package(str, width, pkg);
-               pakfire_package_unref(pkg);
-       }
-
-       // newline
-       pakfire_transaction_add_newline(str, width);
-
-END:
-       pakfire_packagelist_unref(list);
-
-       return c;
-}
-
-static void pakfire_transaction_add_summary_line(char** str, size_t width, const char* headline, size_t pkgs) {
-       if (pkgs > 0)
-               asprintf(str, "%s%-20s %-4zu %s\n", *str, headline, pkgs, _("package(s)"));
-}
-
 static void pakfire_transaction_add_usage_line(char** str, size_t width, const char* headline, ssize_t size) {
        char buffer[128];
        pakfire_format_size(buffer, sizeof(buffer) - 1, size);
@@ -284,8 +287,14 @@ static void pakfire_transaction_add_usage_line(char** str, size_t width, const c
 }
 
 PAKFIRE_EXPORT char* pakfire_transaction_dump(PakfireTransaction transaction, size_t width) {
+       char headline[1024];
        char* string = "";
 
+       Pool* pool = transaction->transaction->pool;
+       const int mode =
+               SOLVER_TRANSACTION_SHOW_OBSOLETES |
+               SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE;
+
        // Header
        pakfire_transaction_add_separator(&string, width);
        pakfire_transaction_add_line(&string, width,
@@ -297,40 +306,146 @@ PAKFIRE_EXPORT char* pakfire_transaction_dump(PakfireTransaction transaction, si
        );
        pakfire_transaction_add_separator(&string, width);
 
-       // Show what we are doing
-       size_t installing = pakfire_transaction_add_section(&string, width, transaction,
-               _("Installing:"), PAKFIRE_STEP_INSTALL);
-       size_t reinstalling = pakfire_transaction_add_section(&string, width, transaction,
-               _("Reinstalling:"), PAKFIRE_STEP_REINSTALL);
-       size_t updating = pakfire_transaction_add_section(&string, width, transaction,
-               _("Updating:"), PAKFIRE_STEP_UPGRADE);
-       size_t downgrading = pakfire_transaction_add_section(&string, width, transaction,
-               _("Downgrading:"), PAKFIRE_STEP_DOWNGRADE);
-       size_t removing = pakfire_transaction_add_section(&string, width, transaction,
-               _("Removing:"), PAKFIRE_STEP_ERASE);
-       size_t obsoleting = pakfire_transaction_add_section(&string, width, transaction,
-               _("Obsoleting:"), PAKFIRE_STEP_OBSOLETE);
+       Queue classes;
+       queue_init(&classes);
+
+       // Get all classes
+       transaction_classify(transaction->transaction, mode, &classes);
+
+       Queue pkgs;
+       queue_init(&pkgs);
+
+       /*
+               The classes queue now contains a list of all classes as a tuple of:
+                       * The class type
+                       * The number of packages in this class
+                       * The from ID (for arch/vendor change)
+                       * The to ID (for arch/vendor change)
+       */
+       for (int i = 0; i < classes.count; i += 4) {
+               Id class = classes.elements[i];
+               unsigned int count = classes.elements[i+1];
+
+               const char* from = pool_id2str(pool, classes.elements[i+2]);
+               const char* to   = pool_id2str(pool, classes.elements[i+3]);
+
+               switch (class) {
+                       case SOLVER_TRANSACTION_INSTALL:
+                               if (count)
+                                       pakfire_string_format(headline, _("Installing %u packages:"), count);
+                               else
+                                       pakfire_string_set(headline, _("Installing one package:"));
+                               break;
+
+                       case SOLVER_TRANSACTION_REINSTALLED:
+                               if (count)
+                                       pakfire_string_format(headline, _("Reinstalling %u packages:"), count);
+                               else
+                                       pakfire_string_set(headline, _("Reinstalling one package:"));
+                               break;
+
+                       case SOLVER_TRANSACTION_ERASE:
+                               if (count)
+                                       pakfire_string_format(headline, _("Removing %u packages:"), count);
+                               else
+                                       pakfire_string_set(headline, _("Removing one package:"));
+                               break;
+
+                       case SOLVER_TRANSACTION_UPGRADED:
+                               if (count)
+                                       pakfire_string_format(headline, _("Updating %u packages:"), count);
+                               else
+                                       pakfire_string_set(headline, _("Updating one package:"));
+                               break;
+
+                       case SOLVER_TRANSACTION_DOWNGRADED:
+                               if (count)
+                                       pakfire_string_format(headline, _("Downgrading %u packages:"), count);
+                               else
+                                       pakfire_string_set(headline, _("Downgrading one package:"));
+                               break;
+
+                       case SOLVER_TRANSACTION_CHANGED:
+                               if (count)
+                                       pakfire_string_format(headline, _("Changing %u packages:"), count);
+                               else
+                                       pakfire_string_set(headline, _("Changing one package:"));
+                               break;
+
+                       case SOLVER_TRANSACTION_ARCHCHANGE:
+                               if (count)
+                                       pakfire_string_format(headline,
+                                               _("%u architecture changes from '%s' to '%s':"), count, from, to);
+                               else
+                                       pakfire_string_format(headline,
+                                               _("One architecture change from '%s' to '%s':"), from, to);
+                               break;
+
+                       case SOLVER_TRANSACTION_VENDORCHANGE:
+                               if (count)
+                                       pakfire_string_format(headline,
+                                               _("%u vendor changes from '%s' to '%s':"), count, from, to);
+                               else
+                                       pakfire_string_format(headline,
+                                               _("One vendor change from '%s' to '%s':"), from, to);
+                               break;
+
+                       case SOLVER_TRANSACTION_IGNORE:
+                               continue;
+               }
+
+               // Show what we are doing
+               pakfire_transaction_add_headline(&string, width, headline);
+
+               // Fetch packages in this class
+               transaction_classify_pkgs(transaction->transaction, mode, class,
+                       classes.elements[i+2], classes.elements[i+3], &pkgs);
+
+               // List all packages
+               for (int j = 0; j < pkgs.count; j++) {
+                       PakfirePackage pkg1 = pakfire_package_create_from_solvable(
+                               transaction->pakfire, pkgs.elements[j]);
+                       PakfirePackage pkg2 = NULL;
+
+                       switch (class) {
+                               case SOLVER_TRANSACTION_UPGRADED:
+                               case SOLVER_TRANSACTION_DOWNGRADED:
+                                       pkg2 = pakfire_package_create_from_solvable(transaction->pakfire,
+                                               transaction_obs_pkg(transaction->transaction, pkgs.elements[j]));
+
+                                       pakfire_transaction_add_package_change(&string, width, pkg1, pkg2);
+                                       break;
+
+                               default:
+                                       pakfire_transaction_add_package(&string, width, pkg1);
+                                       break;
+                       }
+
+                       pakfire_package_unref(pkg1);
+                       if (pkg2)
+                               pakfire_package_unref(pkg2);
+               }
+
+               // Newline
+               pakfire_transaction_add_newline(&string, width);
+       }
+
+       queue_free(&classes);
+       queue_free(&pkgs);
 
        // Summary
        pakfire_transaction_add_headline(&string, width, _("Transaction Summary"));
        pakfire_transaction_add_separator(&string, width);
 
-       pakfire_transaction_add_summary_line(&string, width, _("Installing:"), installing);
-       pakfire_transaction_add_summary_line(&string, width, _("Reinstalling:"), reinstalling);
-       pakfire_transaction_add_summary_line(&string, width, _("Updating:"), updating);
-       pakfire_transaction_add_summary_line(&string, width, _("Downgrading:"), downgrading);
-       pakfire_transaction_add_summary_line(&string, width, _("Removing:"), removing);
-       pakfire_transaction_add_summary_line(&string, width, _("Obsoleting:"), obsoleting);
-
        // How much do we need to download?
        size_t downloadsize = pakfire_transaction_downloadsize(transaction);
+
        if (downloadsize > 0)
                pakfire_transaction_add_usage_line(&string, width,
                        _("Total Download Size"), downloadsize);
 
        // How much more space do we need?
        ssize_t sizechange = pakfire_transaction_installsizechange(transaction);
-
        pakfire_transaction_add_usage_line(&string, width,
                (sizechange >= 0) ? _("Installed Size") : _("Freed Size"), sizechange);
 
@@ -347,9 +462,8 @@ static int pakfire_transaction_run_steps(PakfireTransaction transaction,
        int r = 0;
 
        // Walk through all steps
-       PakfireStep* steps = transaction->steps;
-       while (*steps) {
-               PakfireStep step = *steps++;
+       for (unsigned int i = 0; i < transaction->num_steps; i++) {
+               PakfireStep step = transaction->steps[i];
 
                // Verify the step
                r = pakfire_step_run(step, db, action);
@@ -410,7 +524,6 @@ static int pakfire_transaction_download_package(PakfireTransaction transaction,
        int r = 1;
        PakfireRepo repo = NULL;
        struct pakfire_mirrorlist* mirrorlist = NULL;
-       char* nevra = NULL;
 
        // Fetch the repository to download from
        repo = pakfire_package_get_repo(pkg);
@@ -433,7 +546,7 @@ static int pakfire_transaction_download_package(PakfireTransaction transaction,
        if (!filename)
                goto ERROR;
 
-       nevra = pakfire_package_get_nevra(pkg);
+       const char* nevra = pakfire_package_get_nevra(pkg);
        if (!nevra)
                goto ERROR;
 
@@ -442,8 +555,6 @@ static int pakfire_transaction_download_package(PakfireTransaction transaction,
                nevra, filename, path, 0);
 
 ERROR:
-       if (nevra)
-               free(nevra);
        if (mirrorlist)
                pakfire_mirrorlist_unref(mirrorlist);
        if (repo)