#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>
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 {
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;
}
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++)
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);
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;
}
// Update the runtime linker cache
if (need_ldconfig)
- pakfire_execute_ldconfig(transaction->pakfire);
+ pakfire_jail_ldconfig(transaction->pakfire);
pakfire_filelist_unref(filelist);
}
}
// Update the runtime linker cache after all files have been removed
- pakfire_execute_ldconfig(transaction->pakfire);
+ pakfire_jail_ldconfig(transaction->pakfire);
ERROR:
if (filelist)
// 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:
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,
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);
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
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;
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)
goto ERROR;
ERROR:
+ // Cleanup
free(dump);
return r;