]> git.ipfire.org Git - pakfire.git/commitdiff
build: Find all packages to be installed and create a new repository with them
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 19 Jun 2023 15:27:21 +0000 (15:27 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 19 Jun 2023 15:27:21 +0000 (15:27 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/build.c
src/libpakfire/include/pakfire/transaction.h
src/libpakfire/transaction.c

index 1e6ff126f5c0dac325d5ea6fdb0ffd18b9203454..ae3da46eb70787c29758e01996e8303277fb940f 100644 (file)
@@ -2210,10 +2210,93 @@ ERROR:
        return r;
 }
 
+static int pakfire_build_collect_packages(struct pakfire_build* build, const char* path) {
+       struct pakfire_request* request = NULL;
+       struct pakfire_transaction* transaction = NULL;
+       char* p = NULL;
+       int r;
+
+       // Create a new request
+       r = pakfire_request_create(&request, build->pakfire, 0);
+       if (r) {
+               ERROR(build->pakfire, "Could not create request: %m\n");
+               goto ERROR;
+       }
+
+       // XXX
+       // Install the base system
+       r = pakfire_request_add(request, PAKFIRE_REQ_INSTALL, "ipfire-release",
+               PAKFIRE_REQUEST_ESSENTIAL);
+       if (r) {
+               ERROR(build->pakfire, "Could not install 'ipfire-release': %m\n");
+               goto ERROR;
+       }
+
+       // Solve the request
+       r = pakfire_request_solve(request, 0);
+       if (r) {
+               ERROR(build->pakfire, "Could not solve request\n");
+               goto ERROR;
+       }
+
+       // Get the transaction
+       r = pakfire_request_get_transaction(request, &transaction);
+       if (r) {
+               ERROR(build->pakfire, "Could not fetch transaction: %m\n");
+               goto ERROR;
+       }
+
+       // Empty transaction?
+       if (!pakfire_transaction_count(transaction)) {
+               ERROR(build->pakfire, "The transaction is unexpectedly empty\n");
+               r = 1;
+               goto ERROR;
+       }
+
+       // Dump the transaction
+       p = pakfire_transaction_dump(transaction, 80);
+       if (!p) {
+               ERROR(build->pakfire, "Could not dump the transaction: %m\n");
+               r = 1;
+               goto ERROR;
+       }
+
+       // Log the dump
+       INFO(build->pakfire, "%s\n", p);
+
+       // Download all packages
+       r = pakfire_transaction_download(transaction);
+       if (r) {
+               ERROR(build->pakfire, "Could not download the transaction: %m\n");
+               goto ERROR;
+       }
+
+       // Create a repository with all packages in this transaction
+       r = pakfire_transaction_compose_repo(transaction, NULL, path);
+       if (r) {
+               ERROR(build->pakfire, "Could not create repository: %m\n");
+               goto ERROR;
+       }
+
+       // XXX Should we perform installcheck here?
+
+ERROR:
+       if (transaction)
+               pakfire_transaction_unref(transaction);
+       if (request)
+               pakfire_request_unref(request);
+       if (p)
+               free(p);
+
+       return r;
+}
+
 PAKFIRE_EXPORT int pakfire_build_mkimage(struct pakfire_build* build,
                const char* type, FILE* f) {
        FILE* t = NULL;
+       char packagesdir[PATH_MAX];
        char path[PATH_MAX];
+       char* p = NULL;
        int r;
 
        // Check inputs
@@ -2223,7 +2306,8 @@ PAKFIRE_EXPORT int pakfire_build_mkimage(struct pakfire_build* build,
        }
 
        // Create a path inside the build environment
-       r = pakfire_path(build->pakfire, path, "%s", PAKFIRE_TMP_DIR "/pakfire-image.XXXXXX");
+       r = pakfire_path(build->pakfire, path, "%s",
+               PAKFIRE_TMP_DIR "/pakfire-image.XXXXXX");
        if (r)
                goto ERROR;
 
@@ -2235,6 +2319,21 @@ PAKFIRE_EXPORT int pakfire_build_mkimage(struct pakfire_build* build,
                goto ERROR;
        }
 
+       // Create a path for all packages
+       r = pakfire_path(build->pakfire, packagesdir, "%s",
+               PAKFIRE_TMP_DIR "/pakfire-packages.XXXXXX");
+       if (r)
+               goto ERROR;
+
+       p = pakfire_mkdtemp(packagesdir);
+       if (!p)
+               goto ERROR;
+
+       // Collect all packages
+       r = pakfire_build_collect_packages(build, packagesdir);
+       if (r)
+               goto ERROR;
+
        // Initialize the build environment
        r = pakfire_build_init(build);
        if (r)
@@ -2243,6 +2342,7 @@ PAKFIRE_EXPORT int pakfire_build_mkimage(struct pakfire_build* build,
        const char* args[] = {
                type,
                pakfire_relpath(build->pakfire, path),
+               pakfire_relpath(build->pakfire, packagesdir),
                NULL,
        };
 
@@ -2257,10 +2357,16 @@ PAKFIRE_EXPORT int pakfire_build_mkimage(struct pakfire_build* build,
                goto ERROR;
 
 ERROR:
+       if (t)
+               fclose(t);
+
        // Unlink the temporary file
        if (*path)
                unlink(path);
 
+       // Remove all packages
+       pakfire_rmtree(packagesdir, 0);
+
        return r;
 }
 
index 14236ee0fa9f673ed4ec4082d0b60f69c1d95de0..3f21d07934bd231fe8ab27014d52a98d75cba5a5 100644 (file)
@@ -44,9 +44,14 @@ int pakfire_transaction_download(struct pakfire_transaction* transaction);
 
 #include <solv/solver.h>
 
+#include <pakfire/key.h>
+
 int pakfire_transaction_create(struct pakfire_transaction** transaction,
        struct pakfire* pakfire, Solver* solver);
 
+int pakfire_transaction_compose_repo(struct pakfire_transaction* transaction,
+       struct pakfire_key* key, const char* path);
+
 #endif
 
 #endif /* PAKFIRE_TRANSACTION_H */
index ff5d1f53e194ef77ea4dc7908f2b400d8a1a91b5..4f27363303a8797bca94eec2cf07e56647d8799e 100644 (file)
@@ -1370,3 +1370,38 @@ ERROR:
 
        return r;
 }
+
+int pakfire_transaction_compose_repo(struct pakfire_transaction* transaction,
+               struct pakfire_key* key, const char* path) {
+       struct pakfire_archive* archive = NULL;
+       int r;
+
+       // Allocate an array for all files
+       const char* files[transaction->num + 1];
+       unsigned int num = 0;
+
+       DEBUG(transaction->pakfire, "Writing transaction to %s...\n", path);
+
+       // Open all archives
+       r = pakfire_transaction_open_archives(transaction);
+       if (r)
+               return r;
+
+       // Walk through all steps
+       for (unsigned int i = 0; i < transaction->num; i++) {
+               archive = transaction->archives[i];
+
+               // Skip steps that don't have an archive
+               if (!archive)
+                       continue;
+
+               // Add the path to the archive
+               files[num++] = pakfire_archive_get_path(archive);
+       }
+
+       // Terminate the array
+       files[num] = NULL;
+
+       // Create the repository
+       return pakfire_repo_compose(transaction->pakfire, path, key, files);
+}