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) {
}
}
-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) {
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;
}
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;
}
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);
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);
}
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,
);
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);
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);
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);
if (!filename)
goto ERROR;
- nevra = pakfire_package_get_nevra(pkg);
+ const char* nevra = pakfire_package_get_nevra(pkg);
if (!nevra)
goto ERROR;
nevra, filename, path, 0);
ERROR:
- if (nevra)
- free(nevra);
if (mirrorlist)
pakfire_mirrorlist_unref(mirrorlist);
if (repo)