]> git.ipfire.org Git - pakfire.git/commitdiff
transaction: Refactor composing the transaction dump
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 29 Jun 2021 14:34:20 +0000 (14:34 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 29 Jun 2021 14:34:20 +0000 (14:34 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/transaction.c

index fa54e603ec704837ad238b5183c8ffc89981cfbd..0d2ba8591d6815471575cd989c0f2ddbb5e32abc 100644 (file)
@@ -260,22 +260,53 @@ PAKFIRE_EXPORT ssize_t pakfire_transaction_downloadsize(struct pakfire_transacti
        return size;
 }
 
-static void pakfire_transaction_add_headline(char** str, size_t width, const char* headline) {
-       asprintf(str, "%s%s\n", strdup(*str), headline);
+static void pakfire_transaction_append_line(char*** lines, const char* format, ...) {
+       if (!lines)
+               return;
+
+       char* buffer = NULL;
+       va_list args;
+       int r;
+
+       va_start(args, format);
+       r = vasprintf(&buffer, format, args);
+       va_end(args);
+
+       if (r < 0)
+               return;
+
+       // Count lines
+       unsigned int count = 0;
+       if (*lines) {
+               for (char** l = *lines; *l; l++)
+                       count++;
+       }
+
+       // Increase size of array
+       *lines = reallocarray(*lines, count + 2, sizeof(**lines));
+       if (!*lines)
+               return;
+
+       // Append line and terminate lines
+       (*lines)[count] = buffer;
+       (*lines)[count + 1] = NULL;
 }
 
-static void pakfire_transaction_add_newline(char** str, size_t width) {
-       asprintf(str, "%s\n", strdupa(*str));
+static void pakfire_transaction_add_headline(char*** lines, size_t width, const char* headline) {
+       pakfire_transaction_append_line(lines, "%s\n", headline);
 }
 
-static void pakfire_transaction_add_line(char** str, size_t width, const char* name,
+static void pakfire_transaction_add_newline(char*** lines, size_t width) {
+       pakfire_transaction_append_line(lines, "\n");
+}
+
+static void pakfire_transaction_add_line(char*** lines, size_t width, const char* name,
                const char* arch, const char* version, const char* repo, const char* size) {
-       // XXX need to adapt to size
-       asprintf(str, "%s %-21s %-8s %-21s %-18s %6s \n", strdupa(*str),
+       pakfire_transaction_append_line(lines, " %-21s %-8s %-21s %-18s %6s \n",
                name, arch, version, repo, size);
 }
 
-static void pakfire_transaction_add_package(char** str, size_t width, PakfirePackage pkg) {
+static void pakfire_transaction_add_package(char*** lines, size_t width, PakfirePackage pkg) {
        char size[128];
 
        PakfireRepo repo = pakfire_package_get_repo(pkg);
@@ -283,7 +314,7 @@ static void pakfire_transaction_add_package(char** str, size_t width, PakfirePac
        // Format size
        pakfire_format_size(size, sizeof(size) - 1, pakfire_package_get_size(pkg));
 
-       pakfire_transaction_add_line(str, width,
+       pakfire_transaction_add_line(lines, width,
                pakfire_package_get_name(pkg),
                pakfire_package_get_arch(pkg),
                pakfire_package_get_evr(pkg),
@@ -294,52 +325,77 @@ 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,
+static void pakfire_transaction_add_package_change(char*** lines, size_t width,
                PakfirePackage old_pkg, PakfirePackage new_pkg) {
        // Print the new package first
-       pakfire_transaction_add_package(str, width, new_pkg);
+       pakfire_transaction_add_package(lines, width, new_pkg);
 
-       asprintf(str, "%s   --> %s\n", strdupa(*str), pakfire_package_get_nevra(old_pkg));
+       pakfire_transaction_append_line(lines,
+               "   --> %s\n", pakfire_package_get_nevra(old_pkg));
 }
 
-static void pakfire_transaction_add_separator(char** str, size_t width) {
+static void pakfire_transaction_add_separator(char*** lines, size_t width) {
        char* separator = alloca(width + 1);
 
-       // Make separator of appropriate length
        for (unsigned int i = 0; i < width; i++)
                separator[i] = '=';
        separator[width] = '\0';
 
-       // newline
-       asprintf(str, "%s%s\n", strdupa(*str), separator);
+       pakfire_transaction_append_line(lines, "%s\n", separator);
 }
 
-static void pakfire_transaction_add_usage_line(char** str, size_t width, const char* headline, ssize_t size) {
+static void pakfire_transaction_add_usage_line(char*** lines, size_t width,
+               const char* headline, ssize_t size) {
        char buffer[128];
        pakfire_format_size(buffer, sizeof(buffer) - 1, size);
 
-       asprintf(str, "%s%-21s: %s\n", strdupa(*str), headline, buffer);
+       pakfire_transaction_append_line(lines,  "%-21s: %s\n", headline, buffer);
+}
+
+static char* pakfire_transaction_join_lines(char** lines) {
+       if (!lines)
+               return NULL;
+
+       size_t size = 0;
+
+       // Determine total length
+       for (char** line = lines; *line; line++)
+               size += strlen(*line);
+
+       // Allocate memory large enough to hold the result
+       char* s = calloc(1, size + 1);
+       if (!s)
+               return s;
+
+       char* p = s;
+
+       for (char** line = lines; *line; line++) {
+               p += snprintf(p, s - p - 1, "%s", *line);
+       }
+
+       return s;
 }
 
 PAKFIRE_EXPORT char* pakfire_transaction_dump(struct pakfire_transaction* transaction, size_t width) {
        char headline[1024];
-       char* string = strdup("");
 
        Pool* pool = transaction->transaction->pool;
        const int mode =
                SOLVER_TRANSACTION_SHOW_OBSOLETES |
                SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE;
 
+       char** lines = NULL;
+
        // Header
-       pakfire_transaction_add_separator(&string, width);
-       pakfire_transaction_add_line(&string, width,
+       pakfire_transaction_add_separator(&lines, width);
+       pakfire_transaction_add_line(&lines, width,
                _("Package"),
                _("Arch"),
                _("Version"),
                _("Repository"),
                _("Size")
        );
-       pakfire_transaction_add_separator(&string, width);
+       pakfire_transaction_add_separator(&lines, width);
 
        Queue classes;
        queue_init(&classes);
@@ -430,7 +486,7 @@ PAKFIRE_EXPORT char* pakfire_transaction_dump(struct pakfire_transaction* transa
                }
 
                // Show what we are doing
-               pakfire_transaction_add_headline(&string, width, headline);
+               pakfire_transaction_add_headline(&lines, width, headline);
 
                // Fetch packages in this class
                transaction_classify_pkgs(transaction->transaction, mode, class,
@@ -448,11 +504,11 @@ PAKFIRE_EXPORT char* pakfire_transaction_dump(struct pakfire_transaction* transa
                                        new_pkg = pakfire_package_create_from_solvable(transaction->pakfire,
                                                transaction_obs_pkg(transaction->transaction, pkgs.elements[j]));
 
-                                       pakfire_transaction_add_package_change(&string, width, old_pkg, new_pkg);
+                                       pakfire_transaction_add_package_change(&lines, width, old_pkg, new_pkg);
                                        break;
 
                                default:
-                                       pakfire_transaction_add_package(&string, width, old_pkg);
+                                       pakfire_transaction_add_package(&lines, width, old_pkg);
                                        break;
                        }
 
@@ -462,33 +518,40 @@ PAKFIRE_EXPORT char* pakfire_transaction_dump(struct pakfire_transaction* transa
                }
 
                // Newline
-               pakfire_transaction_add_newline(&string, width);
+               pakfire_transaction_add_newline(&lines, 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_headline(&lines, width, _("Transaction Summary"));
+       pakfire_transaction_add_separator(&lines, width);
 
        // How much do we need to download?
        size_t downloadsize = pakfire_transaction_downloadsize(transaction);
 
        if (downloadsize > 0)
-               pakfire_transaction_add_usage_line(&string, width,
+               pakfire_transaction_add_usage_line(&lines, 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,
+       pakfire_transaction_add_usage_line(&lines, width,
                (sizechange >= 0) ? _("Installed Size") : _("Freed Size"), sizechange);
 
-       // Remove trailing newline
-       pakfire_remove_trailing_newline(string);
+       // Join all lines together
+       char* string = pakfire_transaction_join_lines(lines);
 
        DEBUG(transaction->pakfire, "Transaction: %s\n", string);
 
+       // Free lines
+       if (lines) {
+               for (char** line = lines; *line; line++)
+                       free(*line);
+               free(lines);
+       }
+
        return string;
 }