From: Michael Tremer Date: Sun, 8 Jan 2023 13:28:36 +0000 (+0000) Subject: build: Implement filter_provides/filter_requires X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=79049ef5215369dd94e8242e4f3b24baecf6e8f9;p=people%2Fstevee%2Fpakfire.git build: Implement filter_provides/filter_requires Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/build.c b/src/libpakfire/build.c index 112d842b..57da89d7 100644 --- a/src/libpakfire/build.c +++ b/src/libpakfire/build.c @@ -24,6 +24,9 @@ #include #include +#define PCRE2_CODE_UNIT_WIDTH 8 +#include + #include #include #include @@ -263,11 +266,38 @@ struct pakfire_find_deps_ctx { int dep; struct pakfire_scriptlet* scriptlet; const char* pattern; + 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->pakfire, "Found filter for %s: %s\n", filter, pattern); + + // Compile the regular expression + r = pakfire_compile_regex(build->pakfire, regex, pattern); + if (r) + goto ERROR; + +ERROR: + if (pattern) + free(pattern); + + return r; +} + static int pakfire_build_send_filelist(struct pakfire* pakfire, void* data, int fd) { struct pakfire_find_deps_ctx* ctx = (struct pakfire_find_deps_ctx*)data; struct pakfire_file* file = NULL; @@ -322,7 +352,8 @@ static int pakfire_build_process_deps(struct pakfire* pakfire, void* data, int priority, const char* buffer, const size_t length) { const struct pakfire_find_deps_ctx* ctx = (struct pakfire_find_deps_ctx*)data; char dep[PATH_MAX]; - int r; + pcre2_match_data* match = NULL; + int r = 0; // Nothing to do for an empty buffer if (!buffer || !*buffer) @@ -349,6 +380,46 @@ static int pakfire_build_process_deps(struct pakfire* pakfire, goto SKIP; } + // Check if this dependency should be filtered + if (ctx->filter) { + match = pcre2_match_data_create_from_pattern(ctx->filter, NULL); + if (!match) { + ERROR(pakfire, "Could not allocate PCRE match data: %m\n"); + goto ERROR; + } + + // Perform matching + r = pcre2_jit_match(ctx->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(pakfire, "Could not fetch PCRE error message: %m\n"); + r = 1; + goto ERROR; + } + + ERROR(pakfire, "Could not match the filter: %s\n", error); + r = 1; + goto ERROR; + + // Match! + } else { + DEBUG(pakfire, "Skipping dependency that has been filtered: %s\n", dep); + r = 0; + goto ERROR; + } + } + // Add dependency r = pakfire_package_add_dep(ctx->pkg, ctx->dep, buffer); if (r) { @@ -363,12 +434,16 @@ static int pakfire_build_process_deps(struct pakfire* pakfire, break; } - return 0; + goto ERROR; SKIP: DEBUG(pakfire, "Skipping dependency that is provided by the package itself: %s\n", dep); - return 0; +ERROR: + if (match) + pcre2_match_data_free(match); + + return r; } /* @@ -379,13 +454,14 @@ SKIP: */ static int pakfire_build_find_deps(struct pakfire_build* build, struct pakfire_package* pkg, int dep, const char* script, - struct pakfire_filelist* filelist, const char* pattern) { + struct pakfire_filelist* filelist, const char* pattern, const pcre2_code* filter) { // Construct the context struct pakfire_find_deps_ctx ctx = { .pkg = pkg, .dep = dep, .pattern = pattern, + .filter = filter, // Filelist .filelist = filelist, @@ -409,34 +485,59 @@ 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; int r; + // Fetch the provides filter + r = pakfire_build_make_filter(build, &filter_provides, + makefile, namespace, "filter_provides"); + if (r) { + ERROR(build->pakfire, "Provides filter is broken: %m\n"); + goto ERROR; + } + + // Fetch the requires filter + r = pakfire_build_make_filter(build, &filter_requires, + makefile, namespace, "filter_requires"); + if (r) { + ERROR(build->pakfire, "Requires filter is broken: %m\n"); + goto ERROR; + } + // Find all provides r = pakfire_build_find_deps(build, pkg, - PAKFIRE_PKG_PROVIDES, "find-provides", filelist, NULL); + PAKFIRE_PKG_PROVIDES, "find-provides", filelist, NULL, filter_provides); if (r) - return r; + goto ERROR; // Find all Perl provides r = pakfire_build_find_deps(build, pkg, - PAKFIRE_PKG_PROVIDES, "perl.prov", filelist, "*.pm"); + PAKFIRE_PKG_PROVIDES, "perl.prov", filelist, "*.pm", filter_provides); if (r) - return r; + goto ERROR; // Find all requires r = pakfire_build_find_deps(build, pkg, - PAKFIRE_PKG_REQUIRES, "find-requires", filelist, NULL); + PAKFIRE_PKG_REQUIRES, "find-requires", filelist, NULL, filter_requires); if (r) - return r; + goto ERROR; // Find all Perl requires r = pakfire_build_find_deps(build, pkg, - PAKFIRE_PKG_REQUIRES, "perl.req", filelist, "*.pm"); + PAKFIRE_PKG_REQUIRES, "perl.req", filelist, "*.pm", filter_requires); if (r) - return r; + goto ERROR; - return 0; +ERROR: + if (filter_provides) + pcre2_code_free(filter_provides); + if (filter_requires) + pcre2_code_free(filter_requires); + + return r; } static int append_to_array(char*** array, const char* s) { @@ -519,7 +620,7 @@ static int pakfire_build_package_add_files(struct pakfire_build* build, pakfire_filelist_dump(filelist, 1); // Find dependencies - r = pakfire_build_find_dependencies(build, pkg, filelist); + r = pakfire_build_find_dependencies(build, makefile, namespace, pkg, filelist); if (r) { ERROR(build->pakfire, "Finding dependencies failed: %m\n"); goto ERROR;