From: Michael Tremer Date: Mon, 24 May 2021 12:12:50 +0000 (+0000) Subject: parser: Unify fetching declarations and implement template lookaside X-Git-Tag: 0.9.28~1285^2~90 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=17689fc74555d1e714f2bc13746ea25990025eac;p=pakfire.git parser: Unify fetching declarations and implement template lookaside Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/parser.c b/src/libpakfire/parser.c index e6b6714f2..2ac993925 100644 --- a/src/libpakfire/parser.c +++ b/src/libpakfire/parser.c @@ -275,15 +275,71 @@ int pakfire_parser_apply_declaration(PakfireParser parser, return pakfire_parser_set(parser, declaration->namespace, declaration->name, declaration->value); } +static const char* pakfire_parser_find_template(PakfireParser parser, + char* template, size_t size, const char* namespace) { + DEBUG(parser->pakfire, "Looking up template in namespace '%s'\n", namespace); + + struct pakfire_parser_declaration* d = pakfire_parser_get_declaration( + parser, namespace, "template"); + + const char* value = (d && *d->value) ? d->value : "MAIN"; + + snprintf(template, size, "packages.template:%s", value); + + return template; +} + +static void pakfire_parser_strip_namespace(char** s) { + char* pos = strrchr(*s, '.'); + + if (pos) + (*s)[pos - *s] = '\0'; + else + (*s)[0] = '\0'; +} + static const char* pakfire_parser_get_raw(PakfireParser parser, const char* namespace, const char* name) { - struct pakfire_parser_declaration* d = pakfire_parser_get_declaration(parser, namespace, name); + struct pakfire_parser_declaration* d = NULL; + + // First, perform a simple lookup + d = pakfire_parser_get_declaration(parser, namespace, name); // Return a match when it actually contains a string - if (d) { - if (d->value && *d->value) - return d->value; + if (d) + return d->value; + // We are done, if the namespace is empty + if (!namespace || !*namespace) return NULL; + + char template[NAME_MAX] = ""; + + // If we couldn't find anything, we check if there is a template, and if that + // has our value... + if (pakfire_string_startswith(namespace, "packages.package:")) { + pakfire_parser_find_template(parser, template, sizeof(template) - 1, namespace); + + if (*template) { + d = pakfire_parser_get_declaration(parser, template, name); + if (d) + return d->value; + } + } + + // Create a working copy of namespace + char* n = strdupa(namespace); + + while (n) { + // Strip namespace + pakfire_parser_strip_namespace(&n); + + d = pakfire_parser_get_declaration(parser, n, name); + if (d) + return d->value; + + // End if we have exhausted the namespace + if (!*n) + break; } // Search in parent parser if available @@ -316,51 +372,6 @@ PAKFIRE_EXPORT int pakfire_parser_append(PakfireParser parser, return r; } -static void pakfire_parser_strip_namespace(char** s) { - char* pos = strrchr(*s, '.'); - - if (pos) - *s[pos - *s] = '\0'; - else - *s[0] = '\0'; -} - -static struct pakfire_parser_declaration* pakfire_parser_find_declaration( - PakfireParser parser, const char* namespace, const char* name) { - char* n = ""; - - // Create a working copy of the namespace variable - if (namespace) - n = strdupa(namespace); - - struct pakfire_parser_declaration* d = NULL; - while (1) { - DEBUG(parser->pakfire, "Looking up %s.%s in parser %p\n", n, name, parser); - - // Lookup declaration - d = pakfire_parser_get_declaration(parser, n, name); - - // End if we have found a match - if (d) - break; - - // End if namespace is empty - if (!n || !*n) - break; - - /* - If we did not find a match, we will remove one level of the - namespace and try again... - */ - pakfire_parser_strip_namespace(&n); - } - - if (!d && parser->parent) - d = pakfire_parser_find_declaration(parser->parent, namespace, name); - - return d; -} - static int pakfire_parser_command_logger(Pakfire pakfire, void* data, int priority, const char* line, size_t length) { char** output = (char**)data; @@ -501,20 +512,13 @@ static int pakfire_parser_expand_variables(PakfireParser parser, DEBUG(parser->pakfire, "Expanding variable: %s\n", variable); // Search for a declaration of this variable - struct pakfire_parser_declaration* d = - pakfire_parser_find_declaration(parser, namespace, (const char*)variable); + const char* repl = pakfire_parser_get_raw(parser, namespace, (const char*)variable); // What is its value? - const char* repl = NULL; - if (d && d->value) { - DEBUG(parser->pakfire, "Replacing %%{%s} with %s.%s = '%s'\n", variable, - d->namespace, d->name, d->value); - - repl = d->value; + if (repl) { + DEBUG(parser->pakfire, "Replacing %%{%s} with '%s'\n", variable, repl); } else { DEBUG(parser->pakfire, "Replacing %%{%s} with an empty string\n", variable); - - repl = ""; } // Find the entire matched pattern @@ -523,7 +527,7 @@ static int pakfire_parser_expand_variables(PakfireParser parser, goto ERROR; // Replace all occurrences - char* tmp = pakfire_string_replace(*buffer, (const char*)pattern, repl); + char* tmp = pakfire_string_replace(*buffer, (const char*)pattern, (repl) ? repl : ""); if (!tmp) goto ERROR; @@ -643,7 +647,7 @@ PAKFIRE_EXPORT char** pakfire_parser_list_namespaces(PakfireParser parser, if (namespaces) { int found = 0; - for (const char** namespace = namespaces; *namespace; namespace++) { + for (char** namespace = namespaces; *namespace; namespace++) { if (strcmp(d->namespace, *namespace) == 0) { found = 1; break; @@ -788,6 +792,8 @@ PAKFIRE_EXPORT int pakfire_parser_create_package(PakfireParser parser, char* arch = NULL; char* evr = NULL; + DEBUG(parser->pakfire, "Building package from namespace '%s'\n", namespace); + // Fetch name name = pakfire_parser_get(parser, namespace, "name"); if (!name || !*name) {