]> git.ipfire.org Git - pakfire.git/commitdiff
parser: Unify fetching declarations and implement template lookaside
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 24 May 2021 12:12:50 +0000 (12:12 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 24 May 2021 12:12:50 +0000 (12:12 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/parser.c

index e6b6714f28ecc13c0fd3961005068336399f139f..2ac99392514487bd6fcbc5b42fee0a943ade6fd0 100644 (file)
@@ -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) {