]> git.ipfire.org Git - pakfire.git/commitdiff
repo: Automatically sync local repositories with their index
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 30 Jan 2025 20:51:06 +0000 (20:51 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 30 Jan 2025 20:51:06 +0000 (20:51 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/pakfire/repo.c

index e3c86ea5956587d337c01af237bf40b228384a10..31c8a651d9f18f8de8afa62521ceb8164580e1c3 100644 (file)
@@ -1668,10 +1668,15 @@ struct pakfire_repo_scan_ctx {
        struct pakfire_progress* progress;
 
        // Flags
-       int flags;
+       enum pakfire_repo_scan_flags {
+               PAKFIRE_REPO_SCAN_SKIP_EXISTING = (1 << 0),
+       } flags;
 
        // Counter
        unsigned int num_archives;
+
+       // Packages
+       struct pakfire_packagelist* packages;
 };
 
 typedef int (*pakfire_repo_scan_callback)(
@@ -1738,7 +1743,14 @@ static int __pakfire_repo_scan_archive(struct pakfire_repo* repo,
                struct pakfire_repo_scan_ctx* scan_ctx, FTSENT* entry) {
        struct pakfire_archive* archive = NULL;
        struct pakfire_package* package = NULL;
-       int r;
+       int r = 0;
+
+       // Skip this package if it already exists
+       if (scan_ctx->flags & PAKFIRE_REPO_SCAN_SKIP_EXISTING) {
+               if (pakfire_packagelist_has_path(scan_ctx->packages, entry->fts_path)) {
+                       goto DONE;
+               }
+       }
 
        // Open archive
        r = pakfire_archive_open(&archive, repo->pakfire, entry->fts_path);
@@ -1746,10 +1758,11 @@ static int __pakfire_repo_scan_archive(struct pakfire_repo* repo,
                goto ERROR;
 
        // Import package into the repository
-       r = pakfire_archive_make_package(archive, repo, &package);
+       r = pakfire_repo_import_archive(repo, archive, &package);
        if (r < 0)
                goto ERROR;
 
+DONE:
        // Increment progress bar
        pakfire_progress_increment(scan_ctx->progress, 1);
 
@@ -1789,6 +1802,13 @@ int pakfire_repo_scan(struct pakfire_repo* repo, int flags) {
        if (r)
                goto ERROR;
 
+       // Load all existing packages
+       if (scan_ctx.flags & PAKFIRE_REPO_SCAN_SKIP_EXISTING) {
+               r = pakfire_repo_to_packagelist(repo, &scan_ctx.packages);
+               if (r < 0)
+                       goto ERROR;
+       }
+
        // Start progress (so that we will let the user know something is happening if
        // scanning for files takes a little bit longer...)
        r = pakfire_progress_start(scan_ctx.progress, 0);
@@ -1820,12 +1840,56 @@ int pakfire_repo_scan(struct pakfire_repo* repo, int flags) {
        r = 0;
 
 ERROR:
+       if (scan_ctx.packages)
+               pakfire_packagelist_unref(scan_ctx.packages);
        if (scan_ctx.progress)
                pakfire_progress_unref(scan_ctx.progress);
 
        return r;
 }
 
+static int pakfire_repo_sync_remove(struct pakfire_ctx* ctx, struct pakfire_package* pkg, void* data) {
+       int r;
+
+       // Check if the package is available
+       r = pakfire_package_is_available(pkg);
+       switch (r) {
+               // The package is not available
+               case 0:
+                       // Destroy the package
+                       return pakfire_package_destroy(pkg);
+
+               // The package is available
+               case 1:
+                       return 0;
+
+               // Error
+               default:
+                       return r;
+       }
+
+       return 0;
+}
+
+static int pakfire_repo_sync(struct pakfire_repo* self) {
+       int r;
+
+       // Log action
+       DEBUG(self->ctx, "Syncing %s...\n", pakfire_repo_get_name(self));
+
+       // Remove all packages that have disappeared
+       r = pakfire_repo_walk_packages(self, pakfire_repo_sync_remove, NULL, 0);
+       if (r < 0)
+               return r;
+
+       // We need to find all new packages
+       r = pakfire_repo_scan(self, PAKFIRE_REPO_SCAN_SKIP_EXISTING);
+       if (r < 0)
+               return r;
+
+       return 0;
+}
+
 int pakfire_repo_refresh(struct pakfire_repo* repo, int force) {
        const char* name = pakfire_repo_get_name(repo);
        int r;
@@ -1852,7 +1916,18 @@ int pakfire_repo_refresh(struct pakfire_repo* repo, int force) {
        }
 
        // Refresh metadata
-       return pakfire_repo_refresh_metadata(repo, force);
+       r = pakfire_repo_refresh_metadata(repo, force);
+       if (r < 0)
+               return r;
+
+       // Perform a sync for all local repositories
+       if (pakfire_repo_is_local(repo)) {
+               r = pakfire_repo_sync(repo);
+               if (r < 0)
+                       return r;
+       }
+
+       return 0;
 }
 
 static int pakfire_repo_sign_database(struct pakfire_repo* repo, struct pakfire_key* key,