From 4302c3033fc9459aafb877e9ffe7ad1b9bb3291a Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Mon, 19 Jun 2023 15:27:21 +0000 Subject: [PATCH] build: Find all packages to be installed and create a new repository with them Signed-off-by: Michael Tremer --- src/libpakfire/build.c | 108 ++++++++++++++++++- src/libpakfire/include/pakfire/transaction.h | 5 + src/libpakfire/transaction.c | 35 ++++++ 3 files changed, 147 insertions(+), 1 deletion(-) diff --git a/src/libpakfire/build.c b/src/libpakfire/build.c index 1e6ff126f..ae3da46eb 100644 --- a/src/libpakfire/build.c +++ b/src/libpakfire/build.c @@ -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; } diff --git a/src/libpakfire/include/pakfire/transaction.h b/src/libpakfire/include/pakfire/transaction.h index 14236ee0f..3f21d0793 100644 --- a/src/libpakfire/include/pakfire/transaction.h +++ b/src/libpakfire/include/pakfire/transaction.h @@ -44,9 +44,14 @@ int pakfire_transaction_download(struct pakfire_transaction* transaction); #include +#include + 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 */ diff --git a/src/libpakfire/transaction.c b/src/libpakfire/transaction.c index ff5d1f53e..4f2736330 100644 --- a/src/libpakfire/transaction.c +++ b/src/libpakfire/transaction.c @@ -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); +} -- 2.39.5