From: Michael Tremer Date: Tue, 29 Jun 2021 14:34:20 +0000 (+0000) Subject: transaction: Refactor composing the transaction dump X-Git-Tag: 0.9.28~1166 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1edcb9992b644979400d9a7186a69d133b4bb2fb;p=pakfire.git transaction: Refactor composing the transaction dump Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/transaction.c b/src/libpakfire/transaction.c index fa54e603e..0d2ba8591 100644 --- a/src/libpakfire/transaction.c +++ b/src/libpakfire/transaction.c @@ -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; }