/
githubmirror
/
libmodulemd
Обзор
Документация
Войти
/
githubmirror
/
libmodulemd
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
2.15.2
modulemd/modulemd-dependencies.c
624 строки
17 KB
Petr Písař
Fix warnings about passing unsigned char * to strcmp()
11 янв 2023, 18:33
11 янв 2023, 18:33
3f1996d
Код
Авторство
О чём код?
/* * This file is part of libmodulemd * Copyright (C) 2018 Red Hat, Inc. * * Fedora-License-Identifier: MIT * SPDX-2.0-License-Identifier: MIT * SPDX-3.0-License-Identifier: MIT * * This program is free software. * For more information on the license, see COPYING. * For more information on free software, see <https://www.gnu.org/philosophy/free-sw.en.html>. */ #include <glib.h> #include <yaml.h> #include "modulemd-dependencies.h" #include "modulemd-errors.h" #include "private/glib-extensions.h" #include "private/modulemd-dependencies-private.h" #include "private/modulemd-util.h" #include "private/modulemd-yaml.h" struct _ModulemdDependencies { GObject parent_instance; /* @key: dependent modules. * @value: #GHashTable set of compatible streams */ GHashTable *buildtime_deps; /* @key: dependent modules. * @value: #GHashTable set of compatible streams */ GHashTable *runtime_deps; }; G_DEFINE_TYPE (ModulemdDependencies, modulemd_dependencies, G_TYPE_OBJECT) ModulemdDependencies * modulemd_dependencies_new (void) { return g_object_new (MODULEMD_TYPE_DEPENDENCIES, NULL); } gboolean modulemd_dependencies_equals (ModulemdDependencies *self_1, ModulemdDependencies *self_2) { if (!self_1 && !self_2) { return TRUE; } if (!self_1 || !self_2) { return FALSE; } g_return_val_if_fail (MODULEMD_IS_DEPENDENCIES (self_1), FALSE); g_return_val_if_fail (MODULEMD_IS_DEPENDENCIES (self_2), FALSE); if (!modulemd_hash_table_equals (self_1->buildtime_deps, self_2->buildtime_deps, modulemd_hash_table_sets_are_equal_wrapper)) { return FALSE; } if (!modulemd_hash_table_equals (self_1->runtime_deps, self_2->runtime_deps, modulemd_hash_table_sets_are_equal_wrapper)) { return FALSE; } return TRUE; } ModulemdDependencies * modulemd_dependencies_copy (ModulemdDependencies *self) { g_autoptr (ModulemdDependencies) d = NULL; g_return_val_if_fail (MODULEMD_IS_DEPENDENCIES (self), NULL); d = modulemd_dependencies_new (); g_hash_table_unref (d->buildtime_deps); d->buildtime_deps = g_hash_table_ref (self->buildtime_deps); g_hash_table_unref (d->runtime_deps); d->runtime_deps = g_hash_table_ref (self->runtime_deps); return g_steal_pointer (&d); } static void modulemd_dependencies_finalize (GObject *object) { ModulemdDependencies *self = (ModulemdDependencies *)object; g_clear_pointer (&self->buildtime_deps, g_hash_table_unref); g_clear_pointer (&self->runtime_deps, g_hash_table_unref); G_OBJECT_CLASS (modulemd_dependencies_parent_class)->finalize (object); } static GHashTable * modulemd_dependencies_nested_table_get_or_create (GHashTable *table, const gchar *key) { g_autofree gchar *keyi = NULL; GHashTable *inner = NULL; inner = g_hash_table_lookup (table, key); if (inner != NULL) { return inner; } // We know that the hash table will end up holding on to it for us. keyi = g_strdup (key); inner = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); g_hash_table_insert (table, keyi, inner); keyi = NULL; return inner; } static void modulemd_dependencies_nested_table_add (GHashTable *table, const gchar *key, const gchar *value) { GHashTable *inner = modulemd_dependencies_nested_table_get_or_create (table, key); g_return_if_fail (inner); if (value != NULL) { g_hash_table_add (inner, g_strdup (value)); } } static GStrv modulemd_dependencies_nested_table_values_as_strv (GHashTable *table, const gchar *key) { GHashTable *inner = g_hash_table_lookup (table, key); if (inner == NULL) { g_warning ("Streams requested for unknown module: %s", key); return NULL; } return modulemd_ordered_str_keys_as_strv (inner); } void modulemd_dependencies_add_buildtime_stream (ModulemdDependencies *self, const gchar *module_name, const gchar *module_stream) { g_return_if_fail (MODULEMD_IS_DEPENDENCIES (self)); g_return_if_fail (module_name); g_return_if_fail (module_stream); modulemd_dependencies_nested_table_add ( self->buildtime_deps, module_name, module_stream); } void modulemd_dependencies_set_empty_buildtime_dependencies_for_module ( ModulemdDependencies *self, const gchar *module_name) { g_return_if_fail (MODULEMD_IS_DEPENDENCIES (self)); g_return_if_fail (module_name); modulemd_dependencies_nested_table_add ( self->buildtime_deps, module_name, NULL); } void modulemd_dependencies_clear_buildtime_dependencies (ModulemdDependencies *self) { g_return_if_fail (MODULEMD_IS_DEPENDENCIES (self)); g_hash_table_remove_all (self->buildtime_deps); } GStrv modulemd_dependencies_get_buildtime_modules_as_strv ( ModulemdDependencies *self) { g_return_val_if_fail (MODULEMD_IS_DEPENDENCIES (self), NULL); return modulemd_ordered_str_keys_as_strv (self->buildtime_deps); } GStrv modulemd_dependencies_get_buildtime_streams_as_strv ( ModulemdDependencies *self, const gchar *module) { g_return_val_if_fail (MODULEMD_IS_DEPENDENCIES (self), NULL); return modulemd_dependencies_nested_table_values_as_strv ( self->buildtime_deps, module); } void modulemd_dependencies_add_runtime_stream (ModulemdDependencies *self, const gchar *module_name, const gchar *module_stream) { g_return_if_fail (MODULEMD_IS_DEPENDENCIES (self)); g_return_if_fail (module_name); g_return_if_fail (module_stream); modulemd_dependencies_nested_table_add ( self->runtime_deps, module_name, module_stream); } void modulemd_dependencies_set_empty_runtime_dependencies_for_module ( ModulemdDependencies *self, const gchar *module_name) { g_return_if_fail (MODULEMD_IS_DEPENDENCIES (self)); g_return_if_fail (module_name); modulemd_dependencies_nested_table_add ( self->runtime_deps, module_name, NULL); } void modulemd_dependencies_clear_runtime_dependencies (ModulemdDependencies *self) { g_return_if_fail (MODULEMD_IS_DEPENDENCIES (self)); g_hash_table_remove_all (self->runtime_deps); } GStrv modulemd_dependencies_get_runtime_modules_as_strv (ModulemdDependencies *self) { g_return_val_if_fail (MODULEMD_IS_DEPENDENCIES (self), NULL); return modulemd_ordered_str_keys_as_strv (self->runtime_deps); } GStrv modulemd_dependencies_get_runtime_streams_as_strv (ModulemdDependencies *self, const gchar *module) { g_return_val_if_fail (MODULEMD_IS_DEPENDENCIES (self), NULL); return modulemd_dependencies_nested_table_values_as_strv (self->runtime_deps, module); } static gboolean modulemd_dependencies_validate_deps (GHashTable *deps, GError **error) { GHashTableIter iter; gpointer key; gpointer value; gchar *module_name = NULL; gchar *stream_name = NULL; gssize signedness = 0; g_autoptr (GPtrArray) set = NULL; g_hash_table_iter_init (&iter, deps); while (g_hash_table_iter_next (&iter, &key, &value)) { module_name = (gchar *)key; /* The value is a set of strings. Get it and check them all */ set = modulemd_ordered_str_keys (value, modulemd_strcmp_sort); /* An empty set is always valid */ if (set->len == 0) { g_clear_pointer (&set, g_ptr_array_unref); continue; } /* The first element will determine the signedness for the whole * set. */ if (((const gchar *)g_ptr_array_index (set, 0))[0] == '-') { signedness = -1; } else { signedness = 1; } for (guint i = 1; i < set->len; i++) { stream_name = (gchar *)g_ptr_array_index (set, i); if ((stream_name[0] == '-' && signedness > 0) || (stream_name[0] != '-' && signedness < 0)) { g_set_error (error, MODULEMD_ERROR, MMD_ERROR_VALIDATE, "Runtime dependency %s contained a mix of positive " "and negative entries.", module_name); return FALSE; } } g_clear_pointer (&set, g_ptr_array_unref); } return TRUE; } gboolean modulemd_dependencies_validate (ModulemdDependencies *self, GError **error) { /* Look through all the runtime dependencies */ if (!modulemd_dependencies_validate_deps (self->runtime_deps, error)) { return FALSE; } if (!modulemd_dependencies_validate_deps (self->buildtime_deps, error)) { return FALSE; } return TRUE; } static void modulemd_dependencies_get_property (GObject *object, guint prop_id, GValue *UNUSED (value), GParamSpec *pspec) { switch (prop_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void modulemd_dependencies_set_property (GObject *object, guint prop_id, const GValue *UNUSED (value), GParamSpec *pspec) { switch (prop_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void modulemd_dependencies_class_init (ModulemdDependenciesClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = modulemd_dependencies_finalize; object_class->get_property = modulemd_dependencies_get_property; object_class->set_property = modulemd_dependencies_set_property; } static void modulemd_dependencies_init (ModulemdDependencies *self) { self->buildtime_deps = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_hash_table_destroy); self->runtime_deps = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_hash_table_destroy); } /* === YAML Functions === */ ModulemdDependencies * modulemd_dependencies_parse_yaml (yaml_parser_t *parser, gboolean strict, GError **error) { MODULEMD_INIT_TRACE (); MMD_INIT_YAML_EVENT (event); gboolean done = FALSE; g_autoptr (ModulemdDependencies) d = NULL; g_autoptr (GError) nested_error = NULL; d = modulemd_dependencies_new (); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); while (!done) { YAML_PARSER_PARSE_WITH_EXIT (parser, &event, error); switch (event.type) { case YAML_MAPPING_END_EVENT: done = TRUE; break; case YAML_SCALAR_EVENT: if (g_str_equal ((const gchar *)event.data.scalar.value, "buildrequires")) { g_hash_table_unref (d->buildtime_deps); d->buildtime_deps = modulemd_yaml_parse_nested_set (parser, &nested_error); if (d->buildtime_deps == NULL) { MMD_YAML_ERROR_EVENT_EXIT ( error, event, "Failed to parse buildtime deps: %s", nested_error->message); } } else if (g_str_equal ((const gchar *)event.data.scalar.value, "requires")) { g_hash_table_unref (d->runtime_deps); d->runtime_deps = modulemd_yaml_parse_nested_set (parser, &nested_error); if (d->runtime_deps == NULL) { MMD_YAML_ERROR_EVENT_EXIT ( error, event, "Failed to parse runtime deps: %s", nested_error->message); } } else { SKIP_UNKNOWN (parser, NULL, "Unexpected key in dependencies body: %s", (const gchar *)event.data.scalar.value); break; } break; default: MMD_YAML_ERROR_EVENT_EXIT ( error, event, "Unexpected YAML event in dependencies: %d", event.type); break; } yaml_event_delete (&event); } return g_steal_pointer (&d); } gboolean modulemd_dependencies_emit_yaml (ModulemdDependencies *self, yaml_emitter_t *emitter, GError **error) { MODULEMD_INIT_TRACE (); int ret; g_autoptr (GError) nested_error = NULL; MMD_INIT_YAML_EVENT (event); ret = mmd_emitter_start_mapping ( emitter, YAML_BLOCK_MAPPING_STYLE, &nested_error); if (!ret) { g_propagate_prefixed_error (error, g_steal_pointer (&nested_error), "Failed to start dependencies mapping: "); return FALSE; } if (g_hash_table_size (self->buildtime_deps) != 0) { ret = mmd_emitter_scalar ( emitter, "buildrequires", YAML_PLAIN_SCALAR_STYLE, &nested_error); if (!ret) { g_propagate_prefixed_error ( error, g_steal_pointer (&nested_error), "Failed to emit dependencies buildrequires key: "); return FALSE; } ret = modulemd_yaml_emit_nested_set ( emitter, self->buildtime_deps, &nested_error); if (!ret) { g_propagate_prefixed_error ( error, g_steal_pointer (&nested_error), "Failed to emit buildtime dependencies rpms: "); return FALSE; } } if (g_hash_table_size (self->runtime_deps) != 0) { ret = mmd_emitter_scalar ( emitter, "requires", YAML_PLAIN_SCALAR_STYLE, &nested_error); if (!ret) { g_propagate_prefixed_error ( error, g_steal_pointer (&nested_error), "Failed to emit dependencies run-requires key: "); return FALSE; } ret = modulemd_yaml_emit_nested_set ( emitter, self->runtime_deps, &nested_error); if (!ret) { g_propagate_prefixed_error ( error, g_steal_pointer (&nested_error), "Failed to emit runtime dependencies rpms: "); return FALSE; } } ret = mmd_emitter_end_mapping (emitter, &nested_error); if (!ret) { g_propagate_prefixed_error (error, g_steal_pointer (&nested_error), "Failed to end dependencies mapping"); return FALSE; } return TRUE; } static gboolean requires_module_and_stream (GHashTable *modules, const gchar *module_name, const gchar *stream_name) { GHashTable *streams = NULL; GHashTableIter iter; gpointer key; gpointer value; g_autofree gchar *negated = NULL; streams = g_hash_table_lookup (modules, module_name); /* If the module doesn't appear at all, return false */ if (!streams) { return FALSE; } /* Check whether this module is the empty set (which means "all streams") */ if (g_hash_table_size (streams) == 0) { return TRUE; } /* Check whether it includes the stream name explicitly */ if (g_hash_table_contains (streams, stream_name)) { return TRUE; } /* Get the first item from the table and check if it's a negation */ negated = g_strdup_printf ("-%s", stream_name); g_hash_table_iter_init (&iter, streams); /* We already checked that this hash table is not empty, so if iterating it * fails, something has gone horribly wrong. Wrap this in a * g_return_val_if_fail() to make static analysis happy. */ g_return_val_if_fail (g_hash_table_iter_next (&iter, &key, &value), FALSE); /* If we have a negative value for any entry, they all must be negative. * Check whether we're explicitly excluding the requested stream */ if (((const gchar *)key)[0] == '-' && (!g_hash_table_contains (streams, negated))) { return TRUE; } return FALSE; } gboolean modulemd_dependencies_requires_module_and_stream (ModulemdDependencies *self, const gchar *module_name, const gchar *stream_name) { return requires_module_and_stream ( self->runtime_deps, module_name, stream_name); } gboolean modulemd_dependencies_buildrequires_module_and_stream ( ModulemdDependencies *self, const gchar *module_name, const gchar *stream_name) { return requires_module_and_stream ( self->buildtime_deps, module_name, stream_name); }