]> git.ipfire.org Git - pakfire.git/commitdiff
Implement extracting archives from Python
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 10 Jun 2019 17:34:16 +0000 (18:34 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 10 Jun 2019 17:34:16 +0000 (18:34 +0100)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/_pakfire/archive.c
src/libpakfire/archive.c
src/libpakfire/include/pakfire/archive.h
src/libpakfire/libpakfire.sym
src/pakfire/base.py
src/pakfire/cli.py

index 36ba7f4cfbc0b1db141efc6d29689740ea20ef8e..25b57b3336208bc7baa0db6af6b28b549bffbb80 100644 (file)
@@ -126,7 +126,35 @@ static PyObject* Archive_get_signatures(ArchiveObject* self) {
        return list;
 }
 
+static PyObject* Archive_extract(ArchiveObject* self, PyObject* args) {
+       const char* target = NULL;
+
+       if (!PyArg_ParseTuple(args, "|z", &target))
+               return NULL;
+
+       // Make extraction path
+       char* prefix = pakfire_archive_extraction_path(self->archive, target);
+
+       // Extract payload
+       int r = pakfire_archive_extract(self->archive, prefix, PAKFIRE_ARCHIVE_USE_PAYLOAD);
+       pakfire_free(prefix);
+
+       // Throw an exception on error
+       if (r) {
+               PyErr_SetFromErrno(PyExc_OSError);
+               return NULL;
+       }
+
+       Py_RETURN_NONE;
+}
+
 static struct PyMethodDef Archive_methods[] = {
+       {
+               "extract",
+               (PyCFunction)Archive_extract,
+               METH_VARARGS,
+               NULL
+       },
        {
                "read",
                (PyCFunction)Archive_read,
index 727e48acbe79e344eb2ad0ec092f9757d9d68369..5f90c33db21823f7a1c0141c9e8a6b162e88296b 100644 (file)
@@ -44,6 +44,7 @@
 #include <pakfire/pakfire.h>
 #include <pakfire/parser.h>
 #include <pakfire/private.h>
+#include <pakfire/repo.h>
 #include <pakfire/util.h>
 
 #define BLOCKSIZE      1024 * 1024 // 1MB
@@ -731,6 +732,36 @@ out:
        return r;
 }
 
+PAKFIRE_EXPORT char* pakfire_archive_extraction_path(PakfireArchive archive, const char* target) {
+       PakfireRepo repo = pakfire_repo_create(archive->pakfire, "dummy");
+
+       // Read package metadata
+       PakfirePackage pkg = pakfire_archive_make_package(archive, repo);
+       if (!pkg) {
+               pakfire_repo_unref(repo);
+               return NULL;
+       }
+
+       const char* arch = pakfire_package_get_arch(pkg);
+       int is_source = (strcmp(arch, "src") == 0);
+
+       // Use a good default for source packages
+       if (is_source && !target)
+               target = "/usr/src/packages";
+
+       char* nevra = pakfire_package_get_nevra(pkg);
+
+       // Append package name and version to path
+       char* prefix = pakfire_path_join(target, nevra);
+
+       // Cleanup
+       pakfire_package_unref(pkg);
+       pakfire_repo_unref(repo);
+       pakfire_free(nevra);
+
+       return prefix;
+}
+
 PAKFIRE_EXPORT int pakfire_archive_extract(PakfireArchive archive, const char* prefix, int flags) {
        struct archive* a;
        struct archive* pa = NULL;
@@ -743,6 +774,8 @@ PAKFIRE_EXPORT int pakfire_archive_extract(PakfireArchive archive, const char* p
 
        int use_payload = (flags & PAKFIRE_ARCHIVE_USE_PAYLOAD);
 
+       DEBUG(archive->pakfire, "Extracting %s to %s\n", archive->path, prefix);
+
        if (use_payload)
                pa = archive_open_payload(a);
 
index 1614bbb2f64fd149dc476f798e2aa1a5ef1ad7ed..5d30467a09f3361d09387ce6a7c5e2a6cd9d158e 100644 (file)
@@ -36,7 +36,8 @@ typedef enum pakfire_archive_verify_status {
 } pakfire_archive_verify_status_t;
 
 typedef enum pakfire_archive_flags {
-       PAKFIRE_ARCHIVE_USE_PAYLOAD = 1 << 0,
+       PAKFIRE_ARCHIVE_USE_PAYLOAD                             = 1 << 0,
+       PAKFIRE_ARCHIVE_ADD_FILENAME_PREFIX             = 1 << 1,
 } pakfire_archive_flags_t;
 
 PakfireArchive pakfire_archive_create(Pakfire pakfire);
@@ -50,6 +51,7 @@ PakfireArchive pakfire_archive_open(Pakfire pakfire, const char* path);
 int pakfire_archive_read(PakfireArchive archive, const char* filename,
        void** data, size_t* data_size, int flags);
 int pakfire_archive_extract(PakfireArchive archive, const char* prefix, int flags);
+char* pakfire_archive_extraction_path(PakfireArchive archive, const char* target);
 
 const char* pakfire_archive_get_path(PakfireArchive archive);
 
index efb78b24503a1be0ddb8385ea5b66fd798248530..663d8f0503f0585879a6e47c9462bf6df3f41b4f 100644 (file)
@@ -46,6 +46,7 @@ global:
        pakfire_archive_count_signatures;
        pakfire_archive_create;
        pakfire_archive_extract;
+       pakfire_archive_extraction_path;
        pakfire_archive_get_filelist;
        pakfire_archive_get_format;
        pakfire_archive_get_path;
index 09dc2da47f2faa51a8b64513fa181a1f7059eb8c..6cfdb167937629af09faf01647e21d91fc018b6d 100644 (file)
@@ -233,6 +233,25 @@ class PakfireContext(object):
        def search(self, pattern):
                return self.pakfire.search(pattern)
 
+       def extract(self, filenames, target=None):
+               if target and target == "/":
+                       raise ValueError("Cannot extract to: %s" % target)
+
+               archives = []
+
+               # Open all archives
+               for filename in filenames:
+                       a = _pakfire.Archive(self.pakfire, filename)
+                       archives.append(a)
+
+               # Nothing to do when no archives where opened
+               if not archives:
+                       return
+
+               # Extract them all
+               for archive in archives:
+                       archive.extract(target)
+
        # Transactions
 
        def install(self, requires, **kwargs):
index 8fcf186a31d1e0b28c29454e18cf11d4f0c9bb4f..2a8144059347a2549a871b5ed57d698fb10dbbdc 100644 (file)
@@ -388,37 +388,7 @@ class Cli(object):
 
        def handle_extract(self, ns):
                with self.pakfire(ns) as p:
-                       # Open all packages.
-                       pkgs = []
-                       for pkg in ns.package:
-                               pkg = packages.open(self, None, pkg)
-                               pkgs.append(pkg)
-
-                       target_prefix = ns.target
-
-                       # Search for binary packages.
-                       binary_packages = any([p.type == "binary" for p in pkgs])
-                       source_packages = any([p.type == "source" for p in pkgs])
-
-                       if binary_packages and source_packages:
-                               raise Error(_("Cannot extract mixed package types"))
-
-                       if binary_packages and not target_prefix:
-                               raise Error(_("You must provide an install directory with --target=..."))
-
-                       elif source_packages and not target_prefix:
-                               target_prefix = "/usr/src/packages/"
-
-                       if target_prefix == "/":
-                               raise Error(_("Cannot extract to /."))
-
-                       for pkg in pkgs:
-                               if pkg.type == "binary":
-                                       target_dir = target_prefix
-                               elif pkg.type == "source":
-                                       target_dir = os.path.join(target_prefix, pkg.friendly_name)
-
-                               pkg.extract(message=_("Extracting"), prefix=target_dir)
+                       p.extract(ns.package, target=ns.target)
 
 
 class CliBuilder(Cli):