From 8c35d40753d0d21d24f88583cd66c3924b89cea6 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Fri, 18 Oct 2024 12:54:43 +0000 Subject: [PATCH] snapshots: Add function to create a new snapshot Signed-off-by: Michael Tremer --- src/libpakfire/include/pakfire/pakfire.h | 3 + src/libpakfire/include/pakfire/snapshot.h | 4 +- src/libpakfire/pakfire.c | 18 ++++ src/libpakfire/snapshot.c | 116 ++++++++++++++++++++++ 4 files changed, 140 insertions(+), 1 deletion(-) diff --git a/src/libpakfire/include/pakfire/pakfire.h b/src/libpakfire/include/pakfire/pakfire.h index 987f48576..87acf16b1 100644 --- a/src/libpakfire/include/pakfire/pakfire.h +++ b/src/libpakfire/include/pakfire/pakfire.h @@ -86,6 +86,9 @@ int pakfire_search(struct pakfire* pakfire, const char* what, int flags, int pakfire_check(struct pakfire* pakfire, struct pakfire_filelist* errors); +// Snapshots +int pakfire_update_snapshot(struct pakfire* pakfire); + #ifdef PAKFIRE_PRIVATE #include diff --git a/src/libpakfire/include/pakfire/snapshot.h b/src/libpakfire/include/pakfire/snapshot.h index 845db9930..0e540b3cc 100644 --- a/src/libpakfire/include/pakfire/snapshot.h +++ b/src/libpakfire/include/pakfire/snapshot.h @@ -42,6 +42,8 @@ const char* pakfire_snapshot_path(struct pakfire_snapshot* snapshot); int pakfire_snapshot_mount(struct pakfire_snapshot* snapshot, const char* path); int pakfire_snapshot_umount(struct pakfire_snapshot* snapshot); -#endif +int pakfire_snapshot_make(struct pakfire_snapshot** snapshot, + struct pakfire* pakfire, const char** packages); +#endif /* PAKFIRE_PRIVATE */ #endif /* PAKFIRE_SNAPSHOT_H */ diff --git a/src/libpakfire/pakfire.c b/src/libpakfire/pakfire.c index da88562f9..d17176e59 100644 --- a/src/libpakfire/pakfire.c +++ b/src/libpakfire/pakfire.c @@ -1712,3 +1712,21 @@ ERROR: return r; } + +int pakfire_update_snapshot(struct pakfire* pakfire) { + struct pakfire_snapshot* snapshot = NULL; + int r; + + const char* packages[] = { + "build-essential", + NULL, + }; + + // Make a new snapshot + r = pakfire_snapshot_make(&snapshot, pakfire, packages); + + if (snapshot) + pakfire_snapshot_unref(snapshot); + + return r; +} diff --git a/src/libpakfire/snapshot.c b/src/libpakfire/snapshot.c index d18eb3dbf..80b8b1f11 100644 --- a/src/libpakfire/snapshot.c +++ b/src/libpakfire/snapshot.c @@ -349,3 +349,119 @@ int pakfire_snapshot_umount(struct pakfire_snapshot* snapshot) { return 0; } + +static int pakfire_snapshot_install_packages(struct pakfire* pakfire, const char** packages) { + struct pakfire_transaction* transaction = NULL; + int r; + + // Create a new transaction + r = pakfire_transaction_create(&transaction, pakfire, 0); + if (r) + goto ERROR; + + // Install all build dependencies + for (const char** p = packages; *p; p++) { + r = pakfire_transaction_request(transaction, PAKFIRE_JOB_INSTALL, *p, PAKFIRE_JOB_ESSENTIAL); + if (r < 0) + goto ERROR; + } + + // Also update everything that has already been installed + r = pakfire_transaction_request(transaction, PAKFIRE_JOB_SYNC, NULL, 0); + if (r < 0) + goto ERROR; + + // Solve the transaction + r = pakfire_transaction_solve(transaction, 0, NULL); + if (r) + goto ERROR; + + // Run the transaction + r = pakfire_transaction_run(transaction); + if (r < 0) + goto ERROR; + +ERROR: + if (transaction) + pakfire_transaction_unref(transaction); + + return r; +} + +/* + Creates a new snapshot +*/ +int pakfire_snapshot_make(struct pakfire_snapshot** snapshot, + struct pakfire* pakfire, const char** packages) { + struct pakfire* p = NULL; + char snapshot_path[PATH_MAX]; + char tmp[PATH_MAX]; + const char* path = NULL; + char time[1024]; + int r; + + struct pakfire_ctx* ctx = pakfire_ctx(pakfire); + + // Store the current time + r = pakfire_strftime_now(time, "%Y-%m-%d-%H:%M:%S"); + if (r < 0) + goto ERROR; + + // Make the final snapshot path + r = pakfire_cache_path(pakfire, snapshot_path, "snapshots/%s", time); + if (r < 0) + goto ERROR; + + // Make a new temporary path + r = pakfire_cache_path(pakfire, tmp, "%s", "snapshots/.XXXXXXX"); + if (r < 0) + goto ERROR; + + // Create the temporary directory + path = pakfire_mkdtemp(tmp); + if (!path) { + r = -errno; + goto ERROR; + } + + // Clone the Pakfire instance + r = pakfire_clone(&p, pakfire, tmp); + if (r < 0) { + CTX_ERROR(ctx, "Could not clone pakfire: %s\n", strerror(-r)); + goto ERROR; + } + + // Install packages + r = pakfire_snapshot_install_packages(p, packages); + if (r < 0) + goto ERROR; + + // Close the pakfire instance + pakfire_unref(p); + p = NULL; + + // Move the snapshot to its final place + r = rename(tmp, snapshot_path); + if (r < 0) { + CTX_ERROR(ctx, "Could not move the snapshot to %s: %m\n", snapshot_path); + r = -errno; + goto ERROR; + } + + // Open the snapshot + r = pakfire_snapshot_create(snapshot, ctx, snapshot_path); + if (r < 0) + goto ERROR; + +ERROR: + if (p) + pakfire_unref(p); + if (ctx) + pakfire_ctx_unref(ctx); + + // Cleanup the temporary directory + if (r) + pakfire_rmtree(tmp, 0); + + return r; +} -- 2.39.5