]> git.ipfire.org Git - people/stevee/pakfire.git/blobdiff - src/libpakfire/transaction.c
digests: Split off into a new set of files
[people/stevee/pakfire.git] / src / libpakfire / transaction.c
index aa3faa52218480ee54003dfaaaf42b70294d9bcc..f2f1fbce0f1c87ba289eb590df5dced959eb103f 100644 (file)
 
 #include <pakfire/archive.h>
 #include <pakfire/db.h>
+#include <pakfire/digest.h>
 #include <pakfire/downloader.h>
-#include <pakfire/execute.h>
 #include <pakfire/file.h>
 #include <pakfire/filelist.h>
 #include <pakfire/i18n.h>
+#include <pakfire/jail.h>
 #include <pakfire/logging.h>
 #include <pakfire/package.h>
 #include <pakfire/pakfire.h>
 #include <pakfire/private.h>
 #include <pakfire/repo.h>
+#include <pakfire/string.h>
 #include <pakfire/transaction.h>
 #include <pakfire/ui.h>
 #include <pakfire/util.h>
@@ -53,6 +55,14 @@ struct pakfire_transaction {
        struct pakfire_archive** archives;
        struct pakfire_package** packages;
        size_t num;
+       size_t progress;
+
+       // Callbacks
+       struct pakfire_transaction_callbacks {
+               // Status
+               pakfire_status_callback status;
+               void* status_data;
+       } callbacks;
 };
 
 enum pakfire_actions {
@@ -261,6 +271,48 @@ PAKFIRE_EXPORT struct pakfire_transaction* pakfire_transaction_unref(
        return NULL;
 }
 
+void pakfire_transaction_set_status_callback(struct pakfire_transaction* transaction,
+               pakfire_status_callback callback, void* data) {
+       transaction->callbacks.status = callback;
+       transaction->callbacks.status_data = data;
+}
+
+static int pakfire_transaction_get_progress(struct pakfire_transaction* transaction) {
+       return transaction->progress * 100 / transaction->num;
+}
+
+static void pakfire_transaction_status(struct pakfire_transaction* transaction,
+               const char* message, ...) {
+       char* buffer = NULL;
+       va_list args;
+       int r;
+
+       // Do nothing if callback isn't set
+       if (!transaction->callbacks.status)
+               return;
+
+       // Format the message
+       if (message) {
+               va_start(args, message);
+               r = vasprintf(&buffer, message, args);
+               va_end(args);
+
+               if (r < 0)
+                       return;
+       }
+
+       // Fetch progress
+       const int progress = pakfire_transaction_get_progress(transaction);
+
+       // Call the callback
+       transaction->callbacks.status(transaction->pakfire,
+               transaction->callbacks.status_data, progress, buffer);
+
+       // Cleanup
+       if (buffer)
+               free(buffer);
+}
+
 PAKFIRE_EXPORT size_t pakfire_transaction_count(struct pakfire_transaction* transaction) {
        return transaction->num;
 }
@@ -272,7 +324,7 @@ static ssize_t pakfire_transaction_installsizechange(struct pakfire_transaction*
        return sizechange * 1024;
 }
 
-PAKFIRE_EXPORT ssize_t pakfire_transaction_downloadsize(struct pakfire_transaction* transaction) {
+static ssize_t pakfire_transaction_downloadsize(struct pakfire_transaction* transaction) {
        ssize_t size = 0;
 
        for (unsigned int i = 0; i < transaction->num; i++)
@@ -640,7 +692,7 @@ static int pakfire_transaction_verify(struct pakfire_transaction* transaction,
                return 0;
        }
 
-       enum pakfire_digests digest_type = PAKFIRE_DIGEST_NONE;
+       enum pakfire_digest_types digest_type = 0;
 
        // Fetch digest from package
        const unsigned char* expected_digest = pakfire_package_get_digest(pkg, &digest_type);
@@ -693,11 +745,16 @@ static int pakfire_transaction_run_script(struct pakfire_transaction* transactio
 
 static int pakfire_transaction_extract(struct pakfire_transaction* transaction,
                struct pakfire_package* pkg, struct pakfire_archive* archive) {
-       // Extract payload to the root of the Pakfire instance
-       int r = pakfire_archive_extract(archive, NULL);
+       const char* nevra = pakfire_package_get_nevra(pkg);
+
+       // Update status
+       pakfire_transaction_status(transaction, _("Installing %s..."), nevra);
+
+       // Extract payload
+       int r = pakfire_archive_extract(archive);
        if (r) {
                ERROR(transaction->pakfire, "Could not extract package %s: %m\n",
-                       pakfire_package_get_nevra(pkg));
+                       nevra);
                return r;
        }
 
@@ -708,7 +765,7 @@ static int pakfire_transaction_extract(struct pakfire_transaction* transaction,
 
                // Update the runtime linker cache
                if (need_ldconfig)
-                       pakfire_execute_ldconfig(transaction->pakfire);
+                       pakfire_jail_ldconfig(transaction->pakfire);
 
                pakfire_filelist_unref(filelist);
        }
@@ -742,7 +799,7 @@ static int pakfire_transaction_erase(struct pakfire_transaction* transaction,
        }
 
        // Update the runtime linker cache after all files have been removed
-       pakfire_execute_ldconfig(transaction->pakfire);
+       pakfire_jail_ldconfig(transaction->pakfire);
 
 ERROR:
        if (filelist)
@@ -863,6 +920,12 @@ static int pakfire_transaction_run_step(struct pakfire_transaction* transaction,
 
                // Execute the action of this script
                case PAKFIRE_ACTION_EXECUTE:
+                       // Increment progress
+                       transaction->progress++;
+
+                       // Update progress callback
+                       pakfire_transaction_status(transaction, NULL);
+
                        switch (type) {
                                case PAKFIRE_STEP_INSTALL:
                                case PAKFIRE_STEP_REINSTALL:
@@ -950,6 +1013,24 @@ static int pakfire_transaction_run_steps(struct pakfire_transaction* transaction
                struct pakfire_db* db, enum pakfire_actions action) {
        int r = 0;
 
+       // Update status
+       switch (action) {
+               case PAKFIRE_ACTION_VERIFY:
+                       pakfire_transaction_status(transaction, _("Verifying packages..."));
+                       break;
+
+               case PAKFIRE_ACTION_PRETRANS:
+                       pakfire_transaction_status(transaction, _("Preparing installation..."));
+                       break;
+
+               case PAKFIRE_ACTION_POSTTRANS:
+                       pakfire_transaction_status(transaction, _("Finishing up..."));
+                       break;
+
+               default:
+                       break;
+       }
+
        // Walk through all steps
        for (unsigned int i = 0; i < transaction->num; i++) {
                r = pakfire_transaction_run_step(transaction, db, action,
@@ -1089,7 +1170,7 @@ static int pakfire_transaction_download_package(struct pakfire_transaction* tran
                goto ERROR;
        }
 
-       enum pakfire_digests digest_type = PAKFIRE_DIGEST_NONE;
+       enum pakfire_digest_types digest_type = 0;
 
        // Retrieve package digest
        const unsigned char* digest = pakfire_package_get_digest(pkg, &digest_type);
@@ -1175,7 +1256,8 @@ ERROR:
        return r;
 }
 
-PAKFIRE_EXPORT int pakfire_transaction_run(struct pakfire_transaction* transaction) {
+PAKFIRE_EXPORT int pakfire_transaction_run(
+               struct pakfire_transaction* transaction, int flags) {
        int r;
 
        // Skip running an empty transaction
@@ -1188,7 +1270,7 @@ PAKFIRE_EXPORT int pakfire_transaction_run(struct pakfire_transaction* transacti
        char* dump = pakfire_transaction_dump(transaction, 80);
 
        // Check if we should continue
-       r = pakfire_ui_confirm(transaction->pakfire, dump, _("Is this okay? [y/N]"));
+       r = pakfire_confirm(transaction->pakfire, dump, _("Is this okay? [y/N]"));
        if (r) {
                ERROR(transaction->pakfire, "Transaction aborted upon user request\n");
                goto ERROR;
@@ -1202,6 +1284,10 @@ PAKFIRE_EXPORT int pakfire_transaction_run(struct pakfire_transaction* transacti
        if (r)
                goto ERROR;
 
+       // End here for a dry run
+       if (flags & PAKFIRE_TRANSACTION_DRY_RUN)
+               goto ERROR;
+
        // Download what we need
        r = pakfire_transaction_download(transaction);
        if (r)
@@ -1213,6 +1299,7 @@ PAKFIRE_EXPORT int pakfire_transaction_run(struct pakfire_transaction* transacti
                goto ERROR;
 
 ERROR:
+       // Cleanup
        free(dump);
 
        return r;