]> git.ipfire.org Git - pakfire.git/commitdiff
archive: Show progress when extracting
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 21 Apr 2021 15:15:38 +0000 (15:15 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 21 Apr 2021 15:15:38 +0000 (15:15 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/archive.c

index eb83d1b6cd148bb76461fe3d332dc4a4f5165a51..37d437cef64f14e89c290a6020459639e9547543 100644 (file)
@@ -47,6 +47,7 @@
 #include <pakfire/pakfire.h>
 #include <pakfire/parser.h>
 #include <pakfire/private.h>
+#include <pakfire/progressbar.h>
 #include <pakfire/pwd.h>
 #include <pakfire/repo.h>
 #include <pakfire/scriptlet.h>
@@ -152,13 +153,18 @@ static la_ssize_t pakfire_archive_read_callback(struct archive* a,
        }
 }
 
-static struct archive* pakfire_archive_open_payload(PakfireArchive archive, struct archive* a) {
+static struct archive* pakfire_archive_open_payload(PakfireArchive archive,
+               struct archive* a, size_t* size) {
        // Find the payload
        struct archive_entry* entry;
        int r = find_archive_entry(&entry, a, PAKFIRE_ARCHIVE_FN_PAYLOAD);
        if (r)
                return NULL;
 
+       // Store size
+       if (size)
+               *size = archive_entry_size(entry);
+
        // Allocate a new archive object
        struct archive* payload = archive_read_new();
        if (!payload)
@@ -728,7 +734,7 @@ PAKFIRE_EXPORT int pakfire_archive_read(PakfireArchive archive, const char* file
        if (r)
                goto ERROR;
 
-       payload = pakfire_archive_open_payload(archive, a);
+       payload = pakfire_archive_open_payload(archive, a, NULL);
        if (!payload)
                goto ERROR;
 
@@ -784,8 +790,56 @@ struct pakfire_archive_extractor {
        struct archive* writer;
        const char* prefix;
        PakfireFilelist filelist;
+       struct pakfire_progressbar* progressbar;
 };
 
+static int pakfire_archive_extract_progressbar(
+               PakfireArchive archive, struct pakfire_progressbar** progressbar) {
+       char* name = pakfire_archive_get(archive, "package", "name");
+       char* arch = pakfire_archive_get(archive, "package", "arch");
+
+       char* e = pakfire_archive_get(archive, "package", "epoch");
+       char* v = pakfire_archive_get(archive, "package", "version");
+       char* r = pakfire_archive_get(archive, "package", "release");
+       char* evr = pakfire_package_join_evr(e, v, r);
+
+       int err = pakfire_progressbar_create(progressbar, NULL);
+       if (err)
+               goto ERROR;
+
+       // Add progressbar widgets
+       err = pakfire_progressbar_add_string(*progressbar, "%s-%s.%s", name, evr, arch);
+       if (err)
+               goto ERROR;
+
+       err = pakfire_progressbar_add_bar(*progressbar);
+       if (err)
+               goto ERROR;
+
+       err = pakfire_progressbar_add_percentage(*progressbar);
+       if (err)
+               goto ERROR;
+
+       // Success
+       err = 0;
+
+ERROR:
+       if (name)
+               free(name);
+       if (arch)
+               free(arch);
+       if (e)
+               free(e);
+       if (v)
+               free(v);
+       if (r)
+               free(r);
+       if (evr)
+               free(evr);
+
+       return err;
+}
+
 static int pakfire_archive_extract_entry(PakfireArchive archive,
                struct archive* a, struct archive_entry* entry, void* data) {
        struct pakfire_archive_extractor* extractor = (struct pakfire_archive_extractor*)data;
@@ -794,6 +848,13 @@ static int pakfire_archive_extract_entry(PakfireArchive archive,
        char buffer[PATH_MAX];
        int r = 1;
 
+       // How much of the archive has been read?
+       size_t bytes_read = archive_filter_bytes(a, -1);
+
+       // Update progress
+       if (extractor->progressbar)
+               pakfire_progressbar_update(extractor->progressbar, bytes_read);
+
        // Create a new file object if there is a filelist
        if (extractor->filelist) {
                r = pakfire_file_create(&file, archive->pakfire);
@@ -863,9 +924,11 @@ ERROR:
 }
 
 PAKFIRE_EXPORT int pakfire_archive_extract(PakfireArchive archive, const char* prefix) {
+       struct pakfire_progressbar* progressbar = NULL;
        struct archive* a = NULL;
        struct archive* payload = NULL;
        struct archive* writer = NULL;
+       size_t size;
        int r;
 
        // Use default path if nothing is set
@@ -881,13 +944,18 @@ PAKFIRE_EXPORT int pakfire_archive_extract(PakfireArchive archive, const char* p
                        goto ERROR;
        }
 
+       // Create a progressbar
+       r = pakfire_archive_extract_progressbar(archive, &progressbar);
+       if (r)
+               goto ERROR;
+
        // Open the archive
        r = archive_open(archive, &a);
        if (r)
                goto ERROR;
 
        // Open payload
-       payload = pakfire_archive_open_payload(archive, a);
+       payload = pakfire_archive_open_payload(archive, a, &size);
        if (!payload)
                goto ERROR;
 
@@ -897,22 +965,34 @@ PAKFIRE_EXPORT int pakfire_archive_extract(PakfireArchive archive, const char* p
                goto ERROR;
 
        struct pakfire_archive_extractor extractor = {
-               .writer   = writer,
-               .prefix   = prefix,
-               .filelist = archive->filelist,
+               .writer      = writer,
+               .prefix      = prefix,
+               .filelist    = archive->filelist,
+               .progressbar = progressbar,
        };
 
+       // Start the progressbar
+       r = pakfire_progressbar_start(progressbar, size);
+       if (r)
+               goto ERROR;
+
        // Extract everything
        r = pakfire_archive_walk_entries(archive, payload,
                pakfire_archive_extract_entry, &extractor);
 
 ERROR:
+       // Finish progressbar
+       if (progressbar)
+               pakfire_progressbar_finish(progressbar);
+
        // Destroy the filelist on error
        if (r) {
                pakfire_filelist_unref(archive->filelist);
                archive->filelist = NULL;
        }
 
+       if (progressbar)
+               pakfire_progressbar_unref(progressbar);
        if (writer)
                archive_write_free(writer);
        if (payload)