]> git.ipfire.org Git - pakfire.git/commitdiff
build: Move filtering dependencies into the package object
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 3 Jan 2025 11:33:17 +0000 (11:33 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 3 Jan 2025 11:33:17 +0000 (11:33 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/pakfire/build.c
src/pakfire/package.c
src/pakfire/package.h

index b58556b771360efa08e7fb33b06f7bfceab1a711..383ba13836735e82a28e7512694b0e517e87f6a0 100644 (file)
@@ -25,9 +25,6 @@
 #include <unistd.h>
 #include <uuid/uuid.h>
 
-#define PCRE2_CODE_UNIT_WIDTH 8
-#include <pcre2.h>
-
 #include <pakfire/build.h>
 #include <pakfire/cgroup.h>
 #include <pakfire/config.h>
@@ -314,38 +311,11 @@ struct pakfire_find_deps_ctx {
        int dep;
        struct pakfire_scriptlet* scriptlet;
        int class;
-       const pcre2_code* filter;
 
        struct pakfire_filelist* filelist;
        unsigned int i;
 };
 
-static int pakfire_build_make_filter(struct pakfire_build* build, pcre2_code** regex,
-               struct pakfire_parser* makefile, const char* namespace, const char* filter) {
-       char* pattern = NULL;
-       int r = 0;
-
-       // Fetch the pattern
-       pattern = pakfire_parser_get(makefile, namespace, filter);
-
-       // Nothing if to if there is no or an empty pattern
-       if (!pattern || !*pattern)
-               goto ERROR;
-
-       DEBUG(build->ctx, "Found filter for %s: %s\n", filter, pattern);
-
-       // Compile the regular expression
-       r = pakfire_compile_regex(build->ctx, regex, pattern);
-       if (r)
-               goto ERROR;
-
-ERROR:
-       if (pattern)
-               free(pattern);
-
-       return r;
-}
-
 static ssize_t pakfire_build_send_filelist(
                struct pakfire_ctx* ctx, void* data, char* buffer, size_t length) {
        struct pakfire_find_deps_ctx* p = (struct pakfire_find_deps_ctx*)data;
@@ -408,7 +378,6 @@ static int pakfire_build_process_deps(struct pakfire_ctx* ctx, void* data,
                const char* buffer, const size_t length) {
        const struct pakfire_find_deps_ctx* p = (struct pakfire_find_deps_ctx*)data;
        char dep[PATH_MAX];
-       pcre2_match_data* match = NULL;
        int r = 0;
 
        // Nothing to do for an empty buffer
@@ -433,45 +402,6 @@ static int pakfire_build_process_deps(struct pakfire_ctx* ctx, void* data,
                        goto SKIP;
        }
 
-       // Check if this dependency should be filtered
-       if (p->filter) {
-               match = pcre2_match_data_create_from_pattern(p->filter, NULL);
-               if (!match) {
-                       ERROR(ctx, "Could not allocate PCRE match data: %m\n");
-                       goto ERROR;
-               }
-
-               // Perform matching
-               r = pcre2_jit_match(p->filter, (PCRE2_SPTR)dep, length - 1,
-                       0, 0, match, NULL);
-
-               // No match
-               if (r == PCRE2_ERROR_NOMATCH) {
-                       // Fall through...
-
-               // Handle any errors
-               } else if (r < 0) {
-                       char error[120];
-
-                       // Fetch the error message
-                       r = pcre2_get_error_message(r, (PCRE2_UCHAR*)error, sizeof(error));
-                       if (r < 0) {
-                               ERROR(ctx, "Could not fetch PCRE error message: %m\n");
-                               r = -errno;
-                               goto ERROR;
-                       }
-
-                       ERROR(ctx, "Could not match the filter: %s\n", error);
-                       r = -errno;
-                       goto ERROR;
-
-               // Match!
-               } else {
-                       DEBUG(ctx, "Skipping dependency that has been filtered: %s\n", dep);
-                       goto SKIP;
-               }
-       }
-
        // Add dependency
        r = pakfire_package_add_dep(p->pkg, p->dep, "%s", dep);
        if (r < 0) {
@@ -491,8 +421,6 @@ SKIP:
        r = length;
 
 ERROR:
-       if (match)
-               pcre2_match_data_free(match);
 
        return r;
 }
@@ -738,7 +666,7 @@ static int __pakfire_build_find_requires(
 }
 
 static int pakfire_build_find_requires(struct pakfire_build* build,
-               struct pakfire_package* pkg, struct pakfire_filelist* filelist, const pcre2_code* filter) {
+               struct pakfire_package* pkg, struct pakfire_filelist* filelist) {
        struct pakfire_find_deps_ctx deps = {
                .build = build,
                .pkg   = pkg,
@@ -755,14 +683,13 @@ static int pakfire_build_find_requires(struct pakfire_build* build,
 */
 static int pakfire_build_find_deps(struct pakfire_build* build,
                struct pakfire_package* pkg, int dep, const char* script,
-               struct pakfire_filelist* filelist, int class, const pcre2_code* filter) {
+               struct pakfire_filelist* filelist, int class) {
        // Construct the context
        struct pakfire_find_deps_ctx ctx = {
                .build    = build,
                .pkg      = pkg,
                .dep      = dep,
                .class    = class,
-               .filter   = filter,
 
                // Filelist
                .filelist = filelist,
@@ -794,60 +721,65 @@ static int pakfire_build_find_deps(struct pakfire_build* build,
 static int pakfire_build_find_dependencies(struct pakfire_build* build,
                struct pakfire_parser* makefile, const char* namespace,
                struct pakfire_package* pkg, struct pakfire_filelist* filelist) {
-       pcre2_code* filter_provides = NULL;
-       pcre2_code* filter_requires = NULL;
+       char* filter_provides = NULL;
+       char* filter_requires = NULL;
        int r;
 
        // Fetch the provides filter
-       r = pakfire_build_make_filter(build, &filter_provides,
-               makefile, namespace, "filter_provides");
-       if (r) {
-               ERROR(build->ctx, "Provides filter is broken: %m\n");
-               goto ERROR;
+       filter_provides = pakfire_parser_get(makefile, namespace, "filter_provides");
+       if (filter_provides) {
+               r = pakfire_package_add_dep_filter(pkg, PAKFIRE_PKG_PROVIDES, filter_provides);
+               if (r < 0)
+                       goto ERROR;
        }
 
        // Fetch the requires filter
-       r = pakfire_build_make_filter(build, &filter_requires,
-               makefile, namespace, "filter_requires");
-       if (r) {
-               ERROR(build->ctx, "Requires filter is broken: %m\n");
-               goto ERROR;
+       filter_requires = pakfire_parser_get(makefile, namespace, "filter_requires");
+       if (filter_requires) {
+               r = pakfire_package_add_dep_filter(pkg, PAKFIRE_PKG_REQUIRES, filter_requires);
+               if (r < 0)
+                       goto ERROR;
        }
 
        // Find all provides
        r = pakfire_build_find_deps(build, pkg,
-               PAKFIRE_PKG_PROVIDES, "find-provides", filelist, 0, filter_provides);
+               PAKFIRE_PKG_PROVIDES, "find-provides", filelist, 0);
        if (r)
                goto ERROR;
 
        // Find all Perl provides
        r = pakfire_build_find_deps(build, pkg,
-               PAKFIRE_PKG_PROVIDES, "perl.prov", filelist, PAKFIRE_FILE_PERL, filter_provides);
+               PAKFIRE_PKG_PROVIDES, "perl.prov", filelist, PAKFIRE_FILE_PERL);
        if (r)
                goto ERROR;
 
        // Find all requires
-       r = pakfire_build_find_requires(build, pkg, filelist, filter_requires);
+       r = pakfire_build_find_requires(build, pkg, filelist);
        if (r < 0)
                goto ERROR;
 
        // XXX LEGACY CODE
        r = pakfire_build_find_deps(build, pkg,
-               PAKFIRE_PKG_REQUIRES, "find-requires", filelist, 0, filter_requires);
+               PAKFIRE_PKG_REQUIRES, "find-requires", filelist, 0);
        if (r)
                goto ERROR;
 
        // Find all Perl requires
        r = pakfire_build_find_deps(build, pkg,
-               PAKFIRE_PKG_REQUIRES, "perl.req", filelist, PAKFIRE_FILE_PERL, filter_requires);
+               PAKFIRE_PKG_REQUIRES, "perl.req", filelist, PAKFIRE_FILE_PERL);
        if (r)
                goto ERROR;
 
 ERROR:
-       if (filter_provides)
-               pcre2_code_free(filter_provides);
-       if (filter_requires)
-               pcre2_code_free(filter_requires);
+       if (filter_provides) {
+               pakfire_package_add_dep_filter(pkg, PAKFIRE_PKG_PROVIDES, NULL);
+               free(filter_provides);
+       }
+
+       if (filter_requires) {
+               pakfire_package_add_dep_filter(pkg, PAKFIRE_PKG_REQUIRES, NULL);
+               free(filter_requires);
+       }
 
        return r;
 }
index b0958a558969f750ebec75e017fa7c410d56220c..848ee074eb00a78ea23afaaf1b5682f145909036 100644 (file)
 
 #include <json.h>
 
+// PCRE2
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
+
 #include <solv/evr.h>
 #include <solv/pool.h>
 #include <solv/repo.h>
@@ -65,6 +69,11 @@ struct pakfire_package {
        char filename[NAME_MAX];
        char path[PATH_MAX];
        char cache_path[PATH_MAX];
+
+       struct {
+               pcre2_code* requires;
+               pcre2_code* provides;
+       } filters;
 };
 
 static Solvable* get_solvable(struct pakfire_package* pkg) {
@@ -263,6 +272,10 @@ ERROR:
 }
 
 static void pakfire_package_free(struct pakfire_package* pkg) {
+       if (pkg->filters.requires)
+               pcre2_code_free(pkg->filters.requires);
+       if (pkg->filters.provides)
+               pcre2_code_free(pkg->filters.provides);
        if (pkg->repo)
                pakfire_repo_unref(pkg->repo);
        if (pkg->pakfire)
@@ -1369,6 +1382,94 @@ SUCCESS:
        return ret;
 }
 
+int pakfire_package_add_dep_filter(struct pakfire_package* pkg,
+               const enum pakfire_package_key key, const char* pattern) {
+       pcre2_code* filter = NULL;
+       int r;
+
+       // Compile the filter
+       if (pattern) {
+               r = pakfire_compile_regex(pkg->ctx, &filter, pattern);
+               if (r < 0) {
+                       ERROR(pkg->ctx, "Could not install dependency filter for %s: %s\n",
+                               pakfire_package_get_string(pkg, PAKFIRE_PKG_NEVRA), pattern);
+                       return r;
+               }
+       }
+
+       switch (key) {
+               case PAKFIRE_PKG_PROVIDES:
+                       if (pkg->filters.provides)
+                               pcre2_code_free(pkg->filters.provides);
+
+                       pkg->filters.provides = filter;
+                       break;
+
+               case PAKFIRE_PKG_REQUIRES:
+                       if (pkg->filters.requires)
+                               pcre2_code_free(pkg->filters.requires);
+
+                       pkg->filters.requires = filter;
+                       break;
+
+               default:
+                       pcre2_code_free(filter);
+
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int pakfire_package_filter_dep(struct pakfire_package* pkg,
+               const pcre2_code* filter, const char* dep) {
+       pcre2_match_data* match = NULL;
+       char error[120];
+       int r;
+
+       // Prepare match
+       match = pcre2_match_data_create_from_pattern(filter, NULL);
+       if (!match) {
+               ERROR(pkg->ctx, "Could not allocate PCRE match data: %m\n");
+               r = -errno;
+               goto ERROR;
+       }
+
+       // Perform matching
+       r = pcre2_jit_match(filter, (PCRE2_SPTR)dep, -1, 0, 0, match, NULL);
+       if (r < 0) {
+               switch (r) {
+                       case PCRE2_ERROR_NOMATCH:
+                               r = 0;
+                               goto ERROR;
+
+                       default:
+                               // Fetch the error message
+                               r = pcre2_get_error_message(r, (PCRE2_UCHAR*)error, sizeof(error));
+                               if (r < 0) {
+                                       ERROR(pkg->ctx, "Could not fetch PCRE error message: %m\n");
+                                       r = -errno;
+                                       goto ERROR;
+                               }
+
+                               ERROR(pkg->ctx, "Could not match the filter: %s\n", error);
+                               r = -EINVAL;
+                               goto ERROR;
+               }
+       }
+
+       // Match!
+       DEBUG(pkg->ctx, "%s: Dependency '%s' has been filtered\n",
+               pakfire_package_get_string(pkg, PAKFIRE_PKG_NEVRA), dep);
+       r = 1;
+
+ERROR:
+       if (match)
+               pcre2_match_data_free(match);
+
+       return r;
+}
+
 int pakfire_package_add_dep(struct pakfire_package* pkg,
                const enum pakfire_package_key key, const char* format, ...) {
        char buffer[PATH_MAX];
@@ -1386,6 +1487,35 @@ int pakfire_package_add_dep(struct pakfire_package* pkg,
        if (pakfire_string_startswith(buffer, "#"))
                return 0;
 
+       // Apply filters
+       switch (key) {
+               case PAKFIRE_PKG_PROVIDES:
+                       if (pkg->filters.provides) {
+                               r = pakfire_package_filter_dep(pkg, pkg->filters.provides, buffer);
+                               if (r < 0)
+                                       return r;
+
+                               // Filtered
+                               else if (r == 1)
+                                       return 0;
+                       }
+                       break;
+
+               case PAKFIRE_PKG_REQUIRES:
+                       if (pkg->filters.requires) {
+                               r = pakfire_package_filter_dep(pkg, pkg->filters.requires, buffer);
+                               if (r < 0)
+                                       return r;
+
+                               // Filtered
+                               else if (r == 1)
+                                       return 0;
+                       }
+
+               default:
+                       break;
+       }
+
        // Parse the dependency
        Id id = pakfire_str2dep(pkg->pakfire, buffer);
        if (!id) {
index d1f8519c3fe302e6374b72f7219c9250082b0fb8..87e52ee4a9b9e35cec49ea743ab254c744d42f9e 100644 (file)
@@ -173,6 +173,9 @@ int pakfire_package_is_installed(struct pakfire_package* pkg);
 int pakfire_package_append_file(struct pakfire_package* pkg, const char* path);
 
 // Dependencies
+int pakfire_package_add_dep_filter(struct pakfire_package* pkg,
+       const enum pakfire_package_key key, const char* pattern);
+
 int pakfire_package_add_dep(struct pakfire_package* pkg,
        const enum pakfire_package_key key, const char* format, ...)
        __attribute__((format(printf, 3, 4)));