From: Michael Tremer Date: Fri, 25 Oct 2024 16:38:49 +0000 (+0000) Subject: repo: Refactor scanning once again X-Git-Tag: 0.9.30~871 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bde874841bdad23f4566091b5233f9ca27faddb2;p=pakfire.git repo: Refactor scanning once again I was being lazy. We need to scan recursively. Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/repo.c b/src/libpakfire/repo.c index 52c2b05cb..2af6ea74c 100644 --- a/src/libpakfire/repo.c +++ b/src/libpakfire/repo.c @@ -18,9 +18,9 @@ # # #############################################################################*/ -#include #include #include +#include #include #include #include @@ -1529,15 +1529,85 @@ PAKFIRE_EXPORT int pakfire_repo_clean(struct pakfire_repo* repo, int flags) { return pakfire_rmtree(cache_path, 0); } -static int pakfire_repo_scan_archive(struct pakfire_repo* repo, const char* path) { +struct pakfire_repo_scan_ctx { + // Progress + struct pakfire_progress* progress; + + // Flags + int flags; + + // Counter + unsigned int num_archives; +}; + +typedef int (*pakfire_repo_scan_callback)( + struct pakfire_repo* repo, struct pakfire_repo_scan_ctx* scan_ctx, FTSENT* entry); + +static int __pakfire_repo_scan(struct pakfire_repo* repo, + struct pakfire_repo_scan_ctx* scan_ctx, pakfire_repo_scan_callback callback) { + FTSENT* entry = NULL; + FTS* fts = NULL; + int r; + + // Fetch the repository path + const char* path = pakfire_repo_get_path(repo); + if (!path) + return -EINVAL; + + char* paths[] = { + (char*)path, NULL, + }; + + // Open the path + fts = fts_open(paths, FTS_PHYSICAL|FTS_NOCHDIR|FTS_NOSTAT, NULL); + if (!fts) { + ERROR(repo->ctx, "Could not open %s: %m\n", path); + r = -errno; + goto ERROR; + } + + // Scan for everything + for (;;) { + entry = fts_read(fts); + if (!entry) + break; + + // We only care about actual files + if (!(entry->fts_info & FTS_F)) + continue; + + // Skip anything that doesn't have the correct file extension + if (!pakfire_path_match("**.pfm", entry->fts_path)) + continue; + + // Call the callback + r = callback(repo, scan_ctx, entry); + if (r) + goto ERROR; + } + +ERROR: + if (fts) + fts_close(fts); + + return r; +} + +static int __pakfire_repo_scan_count(struct pakfire_repo* repo, + struct pakfire_repo_scan_ctx* scan_ctx, FTSENT* entry) { + ++scan_ctx->num_archives; + + return 0; +} + +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; - DEBUG(repo->ctx, "Scanning %s...\n", path); - // Open archive - r = pakfire_archive_open(&archive, repo->pakfire, path); + r = pakfire_archive_open(&archive, repo->pakfire, entry->fts_path); if (r < 0) goto ERROR; @@ -1546,6 +1616,9 @@ static int pakfire_repo_scan_archive(struct pakfire_repo* repo, const char* path if (r < 0) goto ERROR; + // Increment progress bar + pakfire_progress_increment(scan_ctx->progress, 1); + ERROR: if (package) pakfire_package_unref(package); @@ -1555,22 +1628,14 @@ ERROR: return r; } -static int pakfire_repo_scan_filter(const struct dirent* dirent) { - // Skip anything hidden - if (*dirent->d_name == '.') - return 0; - - return !!pakfire_path_match("**.pfm", dirent->d_name); -} - PAKFIRE_EXPORT int pakfire_repo_scan(struct pakfire_repo* repo, int flags) { - struct pakfire_progress* progress = NULL; - struct dirent** archives = NULL; - char archive[PATH_MAX]; - int num_archives = 0; - int fd = -EBADF; int r; + // Scan context + struct pakfire_repo_scan_ctx scan_ctx = { + .flags = flags, + }; + // Fetch name const char* name = pakfire_repo_get_name(repo); @@ -1579,63 +1644,41 @@ PAKFIRE_EXPORT int pakfire_repo_scan(struct pakfire_repo* repo, int flags) { if (!path) return -EINVAL; - // Open path - fd = open(path, O_DIRECTORY|O_CLOEXEC); - if (fd < 0) { - switch (errno) { - // If the directory does not exist, there is nothing to scan - case ENOENT: - r = 0; - goto ERROR; - - default: - r = -errno; - goto ERROR; - } - } - - // Find all archives in the directory - num_archives = scandirat(fd, ".", &archives, pakfire_repo_scan_filter, versionsort); - if (num_archives < 0) { - r = num_archives; - goto ERROR; - } - // Create progress indicator - r = pakfire_progress_create(&progress, repo->ctx, + r = pakfire_progress_create(&scan_ctx.progress, repo->ctx, PAKFIRE_PROGRESS_SHOW_COUNTER|PAKFIRE_PROGRESS_SHOW_ELAPSED_TIME, NULL); if (r) goto ERROR; // Add title to progress - r = pakfire_progress_set_title(progress, _("Scanning %s"), name); + r = pakfire_progress_set_title(scan_ctx.progress, _("Scanning %s"), name); if (r) goto ERROR; - // Start progress - r = pakfire_progress_start(progress, num_archives); + // 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); if (r < 0) goto ERROR; - // Scan all packages - for (int i = 0; i < num_archives; i++) { - r = pakfire_path_append(archive, path, archives[i]->d_name); - if (r < 0) - goto ERROR; + // Count how many files we have + r = __pakfire_repo_scan(repo, &scan_ctx, __pakfire_repo_scan_count); + if (r < 0) + goto ERROR; - r = pakfire_repo_scan_archive(repo, archive); - if (r < 0) - goto ERROR; + // Update the progressbar + pakfire_progress_set_max_value(scan_ctx.progress, scan_ctx.num_archives); - // Increment progress bar - pakfire_progress_increment(progress, 1); - } + // Scan all packages + r = __pakfire_repo_scan(repo, &scan_ctx, __pakfire_repo_scan_archive); + if (r < 0) + goto ERROR; // Mark repository data as changed pakfire_repo_has_changed(repo); // Finish the progress - r = pakfire_progress_finish(progress); + r = pakfire_progress_finish(scan_ctx.progress); if (r < 0) goto ERROR; @@ -1643,15 +1686,8 @@ PAKFIRE_EXPORT int pakfire_repo_scan(struct pakfire_repo* repo, int flags) { r = 0; ERROR: - if (archives) { - for (int i = 0; i < num_archives; i++) - free(archives[i]); - free(archives); - } - if (progress) - pakfire_progress_unref(progress); - if (fd >= 0) - close(fd); + if (scan_ctx.progress) + pakfire_progress_unref(scan_ctx.progress); return r; }