(*s)[0] = '\0';
}
+static char* pakfire_parser_join(const char* fmt, const char* val1, const char* val2) {
+ char* result = NULL;
+ int r;
+
+ // Merge both values if both are set
+ if (val1 && *val1 && val2 && *val2) {
+ r = asprintf(&result, fmt, val1, val2);
+ if (r < 0)
+ return NULL;
+
+ return result;
+ }
+
+ // If only one value is set, return that one
+ if (val1 && *val1)
+ return strdup(val1);
+ else if (val2 && *val2)
+ return strdup(val2);
+
+ // Return an empty string if no value is set
+ return strdup("");
+}
+
static struct pakfire_parser_declaration* pakfire_parser_find_declaration(
struct pakfire_parser* parser, const char* namespace, const char* name) {
struct pakfire_parser_declaration* d;
int pakfire_parser_set(struct pakfire_parser* parser,
const char* namespace, const char* name, const char* value, int flags) {
+ char* buffer = NULL;
+
if (!name)
return -EINVAL;
// Handle when name already exists
struct pakfire_parser_declaration* d = pakfire_parser_get_declaration(parser, namespace, name);
if (d) {
+ if (flags & PAKFIRE_PARSER_DECLARATION_APPEND) {
+ buffer = pakfire_parser_join("%s %s", d->value, value);
+ if (!buffer)
+ return 1;
+
+ // Reset the append flag
+ flags &= ~PAKFIRE_PARSER_DECLARATION_APPEND;
+ } else {
+ buffer = strdup(value);
+ }
+
// Replace value
if (d->value)
free(d->value);
- if (value)
- d->value = strdup(value);
- else
- d->value = NULL;
+ d->value = buffer;
// Update flags
if (flags)
// Import flags
d->flags = flags;
- DEBUG(parser->pakfire, "%p: New declaration: %s.%s = %s\n",
- parser, d->namespace, d->name, d->value);
+ DEBUG(parser->pakfire, "%p: New declaration (%d): %s.%s %s= %s\n",
+ parser,
+ d->flags,
+ d->namespace,
+ d->name,
+ (d->flags & PAKFIRE_PARSER_DECLARATION_APPEND) ? "+" : "",
+ d->value);
// Assign new declaration to array
parser->declarations = reallocarray(parser->declarations,
int pakfire_parser_apply_declaration(struct pakfire_parser* parser,
struct pakfire_parser_declaration* declaration) {
- if (declaration->flags & PAKFIRE_PARSER_DECLARATION_APPEND)
- return pakfire_parser_append(parser, declaration->namespace, declaration->name, declaration->value);
+ DEBUG(parser->pakfire, "GOT HERE %d\n", declaration->flags);
return pakfire_parser_set(parser, declaration->namespace,
declaration->name, declaration->value, declaration->flags);
}
int pakfire_parser_merge(struct pakfire_parser* parser1, struct pakfire_parser* parser2) {
+ struct pakfire_parser_declaration* d = NULL;
+ char* namespace = NULL;
+ char* value = NULL;
+ int r;
+
DEBUG(parser1->pakfire, "Merging parsers %p and %p\n", parser1, parser2);
- char namespace[NAME_MAX*2+1];
if (!parser2) {
errno = EINVAL;
return EINVAL;
for (unsigned int i = 0; i < parser2->num_declarations; i++) {
- struct pakfire_parser_declaration* d = parser2->declarations[i];
+ d = parser2->declarations[i];
if (!d)
break;
- if (parser2->namespace && *d->namespace)
- pakfire_string_format(namespace, "%s.%s", parser2->namespace, d->namespace);
- else if (parser2->namespace)
- pakfire_string_set(namespace, parser2->namespace);
- else if (*d->namespace)
- pakfire_string_set(namespace, d->namespace);
- else
- pakfire_string_set(namespace, "");
+ // Make the new namespace
+ namespace = pakfire_parser_join("%s.%s", parser2->namespace, d->namespace);
+ if (!namespace) {
+ r = 1;
+ goto OUT;
+ }
+
+ const char* old_value = NULL;
- int r = pakfire_parser_set(parser1, namespace, d->name, d->value, d->flags);
+ // Fetch the old value if we are supposed to be appending
+ if (d->flags & PAKFIRE_PARSER_DECLARATION_APPEND) {
+ old_value = pakfire_parser_get_raw(parser1, namespace, d->name);
+
+ // XXX This is not ideal, to only reset once we have found an old
+ // value because we might carry this over too far.
+ // However, this is the only way to fix #12997
+ if (old_value)
+ d->flags &= ~PAKFIRE_PARSER_DECLARATION_APPEND;
+ }
+
+ // Make the new value
+ value = pakfire_parser_join("%s %s", old_value, d->value);
+ if (!value) {
+ r = 1;
+ goto OUT;
+ }
+
+ // Set everything in parser 1
+ r = pakfire_parser_set(parser1, namespace, d->name, value, d->flags);
if (r)
- return r;
+ goto OUT;
+
+OUT:
+ if (namespace)
+ free(namespace);
+ if (value)
+ free(value);
+
+ if (r)
+ break;
}
- return 0;
+ return r;
}
int pakfire_parser_read(struct pakfire_parser* parser, FILE* f,