/
githubmirror
/
libmodulemd
Обзор
Документация
Войти
/
githubmirror
/
libmodulemd
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
libmodulemd-2.15.0
modulemd/modulemd-module.c
1 110 строк
32 KB
Stephen Gallagher
Add support for stripping XMD from an Index
31 янв 2022, 13:02
31 янв 2022, 13:02
5d29686
Код
Авторство
О чём код?
/* * 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 <inttypes.h> #include <yaml.h> #include "modulemd-errors.h" #include "modulemd-module.h" #include "private/glib-extensions.h" #include "private/modulemd-module-private.h" #include "private/modulemd-module-stream-private.h" #include "private/modulemd-translation-private.h" #include "private/modulemd-obsoletes-private.h" #include "private/modulemd-util.h" #include "private/modulemd-yaml.h" struct _ModulemdModule { GObject parent_instance; gchar *module_name; GPtrArray *streams; ModulemdDefaults *defaults; GHashTable *translations; GPtrArray *obsoletes; }; G_DEFINE_TYPE (ModulemdModule, modulemd_module, G_TYPE_OBJECT) enum { PROP_0, PROP_MODULE_NAME, N_PROPS }; static GParamSpec *properties[N_PROPS]; ModulemdModule * modulemd_module_new (const gchar *module_name) { return g_object_new (MODULEMD_TYPE_MODULE, "module-name", module_name, NULL); } ModulemdModule * modulemd_module_copy (ModulemdModule *self) { g_autoptr (ModulemdModule) m = NULL; g_return_val_if_fail (MODULEMD_IS_MODULE (self), NULL); gsize i = 0; m = modulemd_module_new (modulemd_module_get_module_name (self)); m->defaults = modulemd_defaults_copy (self->defaults); for (i = 0; i < self->streams->len; i++) { g_ptr_array_add (m->streams, g_ptr_array_index (self->streams, i)); } for (i = 0; i < self->obsoletes->len; i++) { g_ptr_array_add ( m->obsoletes, modulemd_obsoletes_copy (g_ptr_array_index (self->obsoletes, i))); } return g_steal_pointer (&m); } gboolean modulemd_module_validate (ModulemdModule *UNUSED (self), GError **UNUSED (error)) { /* No validation yet */ return TRUE; } static void modulemd_module_finalize (GObject *object) { ModulemdModule *self = (ModulemdModule *)object; g_clear_pointer (&self->module_name, g_free); g_clear_object (&self->defaults); g_clear_pointer (&self->streams, g_ptr_array_unref); g_clear_pointer (&self->translations, g_hash_table_unref); g_clear_pointer (&self->obsoletes, g_ptr_array_unref); G_OBJECT_CLASS (modulemd_module_parent_class)->finalize (object); } static void modulemd_module_set_module_name (ModulemdModule *self, const gchar *module_name) { g_return_if_fail (MODULEMD_IS_MODULE (self)); g_return_if_fail (module_name); g_clear_pointer (&self->module_name, g_free); self->module_name = g_strdup (module_name); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODULE_NAME]); } const gchar * modulemd_module_get_module_name (ModulemdModule *self) { g_return_val_if_fail (MODULEMD_IS_MODULE (self), NULL); return self->module_name; } static void modulemd_module_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { ModulemdModule *self = MODULEMD_MODULE (object); switch (prop_id) { case PROP_MODULE_NAME: g_value_set_string (value, modulemd_module_get_module_name (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void modulemd_module_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { ModulemdModule *self = MODULEMD_MODULE (object); switch (prop_id) { case PROP_MODULE_NAME: modulemd_module_set_module_name (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void modulemd_module_class_init (ModulemdModuleClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = modulemd_module_finalize; object_class->get_property = modulemd_module_get_property; object_class->set_property = modulemd_module_set_property; properties[PROP_MODULE_NAME] = g_param_spec_string ( "module-name", "Module name", "The name of this module.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_properties (object_class, N_PROPS, properties); } static void modulemd_module_init (ModulemdModule *self) { self->streams = g_ptr_array_new_full (0, g_object_unref); self->translations = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); self->obsoletes = g_ptr_array_new_full (0, g_object_unref); } ModulemdDefaultsVersionEnum modulemd_module_set_defaults (ModulemdModule *self, ModulemdDefaults *defaults, ModulemdDefaultsVersionEnum index_mdversion, GError **error) { g_autoptr (ModulemdDefaults) upgraded_defaults = NULL; g_autoptr (GError) nested_error = NULL; g_return_val_if_fail (MODULEMD_IS_MODULE (self), MD_DEFAULTS_VERSION_ERROR); if (defaults == NULL) { /* If we are empty here, return MD_DEFAULTS_VERSION_UNSET to report * a successful unsetting. */ g_clear_object (&self->defaults); return MD_DEFAULTS_VERSION_UNSET; } /* We should never get a defaults object added whose module name doesn't * match. */ if (g_strcmp0 (modulemd_defaults_get_module_name (defaults), modulemd_module_get_module_name (self)) != 0) { g_set_error (error, MODULEMD_ERROR, MMD_ERROR_VALIDATE, "Attempted to add defaults for module '%s' to module '%s'", modulemd_defaults_get_module_name (defaults), modulemd_module_get_module_name (self)); return MD_DEFAULTS_VERSION_ERROR; } /* For Modulemd.ModuleIndex, we always want all entries to have the same * version, so that merges can be performed. If this Defaults object has a * lower mdversion than the Index, upgrade it to that version. * * We only call this if the mdversion is definitely lower, because the * upgrade() routine is not designed to handle downgrades. */ if (modulemd_defaults_get_mdversion (defaults) < (guint64)index_mdversion) { upgraded_defaults = modulemd_defaults_upgrade (defaults, index_mdversion, &nested_error); if (!upgraded_defaults) { g_propagate_error (error, g_steal_pointer (&nested_error)); return MD_DEFAULTS_VERSION_ERROR; } } else { /* The new defaults were of the same or a higher version, so just copy it * and return that. The ModulemdModuleIndex will handle upgrading other * Defaults in the index to match. */ upgraded_defaults = modulemd_defaults_copy (defaults); } /* Return the mdversion we saved so that the Index can check to see if we * need to upgrade other modules to match. */ g_clear_object (&self->defaults); self->defaults = g_steal_pointer (&upgraded_defaults); return modulemd_defaults_get_mdversion (self->defaults); } ModulemdDefaults * modulemd_module_get_defaults (ModulemdModule *self) { g_return_val_if_fail (MODULEMD_IS_MODULE (self), NULL); return self->defaults; } ModulemdModuleStreamVersionEnum modulemd_module_add_stream (ModulemdModule *self, ModulemdModuleStream *stream, ModulemdModuleStreamVersionEnum index_mdversion, GError **error) { ModulemdModuleStream *old = NULL; ModulemdTranslation *translation = NULL; ModulemdObsoletes *obsoletes = NULL; ModulemdModuleStream *newstream = NULL; g_autoptr (ModulemdModule) newmodule = NULL; g_autoptr (GError) nested_error = NULL; ModulemdModuleStreamVersionEnum new_mdversion; const gchar *module_name = NULL; const gchar *stream_name = NULL; GPtrArray *allstreams; g_return_val_if_fail (MODULEMD_IS_MODULE (self), MD_MODULESTREAM_VERSION_ERROR); g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM (stream), MD_MODULESTREAM_VERSION_ERROR); module_name = modulemd_module_stream_get_module_name (stream); stream_name = modulemd_module_stream_get_stream_name (stream); if (!module_name) { g_set_error ( error, MODULEMD_ERROR, MMD_ERROR_VALIDATE, "Attempted to add stream with no module name to module '%s'", modulemd_module_get_module_name (self)); return MD_MODULESTREAM_VERSION_ERROR; } if (!stream_name) { g_set_error ( error, MODULEMD_ERROR, MMD_ERROR_VALIDATE, "Attempted to add stream with no stream name to module '%s'", modulemd_module_get_module_name (self)); return MD_MODULESTREAM_VERSION_ERROR; } /* We should never get a stream object added whose module name doesn't * match. */ if (g_strcmp0 (module_name, modulemd_module_get_module_name (self)) != 0) { g_set_error (error, MODULEMD_ERROR, MMD_ERROR_VALIDATE, "Attempted to add stream for module '%s' to module '%s'", module_name, modulemd_module_get_module_name (self)); return MD_MODULESTREAM_VERSION_ERROR; } old = modulemd_module_get_stream_by_NSVCA ( self, modulemd_module_stream_get_stream_name (stream), modulemd_module_stream_get_version (stream), modulemd_module_stream_get_context (stream), modulemd_module_stream_get_arch (stream), &nested_error); if (old != NULL) { /* We're probably deduplicating content here, so remove the old one in * favor of the new one. */ if (!modulemd_module_stream_equals (old, stream)) { g_autofree gchar *nsvca = modulemd_module_stream_get_NSVCA_as_string (stream); /* The two streams have matching NSVCA, but differ in content */ g_set_error (error, MODULEMD_ERROR, MMD_ERROR_VALIDATE, "Encountered two streams with matching NSVCA %s but " "differing content", nsvca); return MD_MODULESTREAM_VERSION_ERROR; } /* First, drop the existing stream */ g_ptr_array_remove (self->streams, old); old = NULL; } else if (old == NULL && g_error_matches (nested_error, MODULEMD_ERROR, MMD_ERROR_TOO_MANY_MATCHES)) { /* It should be impossible to get more than one error back here */ g_propagate_error (error, g_steal_pointer (&nested_error)); return MD_MODULESTREAM_VERSION_ERROR; } g_clear_error (&nested_error); obsoletes = modulemd_module_get_newest_active_obsoletes ( self, stream_name, modulemd_module_stream_get_context (stream)); if (obsoletes && index_mdversion < MD_MODULESTREAM_VERSION_TWO) { /* Obsoletes work only with mdversion two and higher */ g_set_error_literal ( error, MODULEMD_ERROR, MMD_ERROR_UPGRADE, "ModuleStream obsoletes requires mdversion two or greater."); return MD_MODULESTREAM_VERSION_ERROR; } if (modulemd_module_stream_get_mdversion (stream) < (guint64)index_mdversion) { /* If the stream we were passed is of a lower mdversion version than the * index, upgrade it to the index version. */ newmodule = modulemd_module_stream_upgrade_ext ( stream, index_mdversion, &nested_error); if (!newmodule) { g_propagate_error (error, g_steal_pointer (&nested_error)); return MD_MODULESTREAM_VERSION_ERROR; } new_mdversion = index_mdversion; } else { /* Otherwise the current stream is already at the desired mdversion, add * it to a new temporary module. */ newmodule = modulemd_module_new (module_name); g_ptr_array_add (newmodule->streams, g_object_ref (stream)); new_mdversion = modulemd_module_stream_get_mdversion (stream); } /* loop through all streams in the index of (possibly upgraded) modules */ allstreams = modulemd_module_get_all_streams (newmodule); for (guint i = 0; i < allstreams->len; i++) { newstream = g_ptr_array_index (allstreams, i); g_ptr_array_add (self->streams, g_object_ref (newstream)); translation = g_hash_table_lookup ( self->translations, modulemd_module_stream_get_stream_name (stream)); if (translation != NULL) { modulemd_module_stream_associate_translation (newstream, translation); } if (obsoletes != NULL) { switch (new_mdversion) { case MD_MODULESTREAM_VERSION_TWO: modulemd_module_stream_v2_associate_obsoletes ( (ModulemdModuleStreamV2 *)newstream, obsoletes); break; default: g_return_val_if_reached (MD_MODULESTREAM_VERSION_ERROR); } } } g_clear_object (&newmodule); return new_mdversion; } GStrv modulemd_module_get_stream_names_as_strv (ModulemdModule *self) { g_return_val_if_fail (MODULEMD_IS_MODULE (self), NULL); if (!self->streams) { return NULL; } g_autoptr (GHashTable) stream_names = g_hash_table_new (g_str_hash, g_str_equal); for (guint i = 0; i < self->streams->len; i++) { g_hash_table_add (stream_names, (void *)modulemd_module_stream_get_stream_name ( g_ptr_array_index (self->streams, i))); } return modulemd_ordered_str_keys_as_strv (stream_names); } GPtrArray * modulemd_module_get_all_streams (ModulemdModule *self) { g_return_val_if_fail (MODULEMD_IS_MODULE (self), NULL); return self->streams; } GPtrArray * modulemd_module_get_streams_by_stream_name_as_list (ModulemdModule *self, const gchar *stream_name) { g_return_val_if_fail (MODULEMD_IS_MODULE (self), NULL); return modulemd_module_search_streams (self, stream_name, 0, NULL, NULL); } ModulemdModuleStream * modulemd_module_get_stream_by_NSVC (ModulemdModule *self, const gchar *stream_name, const guint64 version, const gchar *context) { return modulemd_module_get_stream_by_NSVCA ( self, stream_name, version, context, NULL, NULL); } GPtrArray * modulemd_module_search_streams_by_glob (ModulemdModule *self, const gchar *stream_name, const gchar *version, const gchar *context, const gchar *arch) { gsize i = 0; g_autoptr (GPtrArray) matching_streams = NULL; ModulemdModuleStream *under_consideration = NULL; g_autofree gchar *version_str = NULL; g_return_val_if_fail (MODULEMD_IS_MODULE (self), NULL); /* Assume the worst-case scenario that all streams match to spare us extra * mallocs. */ matching_streams = g_ptr_array_sized_new (self->streams->len); for (i = 0; i < self->streams->len; i++) { g_clear_pointer (&version_str, g_free); under_consideration = (ModulemdModuleStream *)g_ptr_array_index (self->streams, i); /* Skip this one unless the stream name matches */ if (!modulemd_fnmatch ( stream_name, modulemd_module_stream_get_stream_name (under_consideration))) { continue; } /* Skip this one unless the stream version matches OR the version is zero * which indicates that it shouldn't prevent the other cases from * matching. */ if (version) { version_str = g_strdup_printf ( "%" PRIu64, modulemd_module_stream_get_version (under_consideration)); if (!modulemd_fnmatch (version, version_str)) { continue; } } if (!modulemd_fnmatch ( context, modulemd_module_stream_get_context (under_consideration))) { continue; } if (!modulemd_fnmatch ( arch, modulemd_module_stream_get_arch (under_consideration))) { continue; } g_ptr_array_add (matching_streams, under_consideration); } g_ptr_array_sort (matching_streams, compare_streams); return g_steal_pointer (&matching_streams); } GPtrArray * modulemd_module_search_streams_by_nsvca_glob (ModulemdModule *self, const gchar *nsvca_pattern) { gsize i = 0; g_autoptr (GPtrArray) matching_streams = NULL; ModulemdModuleStream *under_consideration = NULL; g_autofree gchar *nsvca = NULL; g_return_val_if_fail (MODULEMD_IS_MODULE (self), NULL); /* Assume the worst-case scenario that all streams match to spare us extra * mallocs. */ matching_streams = g_ptr_array_sized_new (self->streams->len); for (i = 0; i < self->streams->len; i++) { under_consideration = (ModulemdModuleStream *)g_ptr_array_index (self->streams, i); nsvca = modulemd_module_stream_get_NSVCA_as_string (under_consideration); if (nsvca_pattern == NULL || modulemd_fnmatch (nsvca_pattern, nsvca)) { g_ptr_array_add (matching_streams, under_consideration); } g_clear_pointer (&nsvca, g_free); } return g_steal_pointer (&matching_streams); } GPtrArray * modulemd_module_search_streams (ModulemdModule *self, const gchar *stream_name, const guint64 version, const gchar *context, const gchar *arch) { g_autofree gchar *version_str = NULL; g_return_val_if_fail (MODULEMD_IS_MODULE (self), NULL); if (version) { version_str = g_strdup_printf ("%" PRIu64, version); } return modulemd_module_search_streams_by_glob ( self, stream_name, version_str, context, arch); } ModulemdModuleStream * modulemd_module_get_stream_by_NSVCA (ModulemdModule *self, const gchar *stream_name, const guint64 version, const gchar *context, const gchar *arch, GError **error) { g_autoptr (GPtrArray) matching_streams = NULL; g_return_val_if_fail (MODULEMD_IS_MODULE (self), NULL); matching_streams = modulemd_module_search_streams (self, stream_name, version, context, arch); if (matching_streams->len == 0) { g_set_error ( error, MODULEMD_ERROR, MMD_ERROR_NO_MATCHES, "No streams matched"); return NULL; } if (matching_streams->len > 1) { g_set_error (error, MODULEMD_ERROR, MMD_ERROR_TOO_MANY_MATCHES, "Multiple ModulemdModuleStreams matched"); return NULL; } /* Exactly one result, so return it */ return g_ptr_array_index (matching_streams, 0); } typedef struct _modulemd_nsvca { const gchar *stream_name; guint64 version; const gchar *context; const gchar *arch; } modulemd_nsvca; static void modulemd_nsvca_free (gpointer nsvca) { /* All of the fields are just pointers to static data, * so nothing to free here. */ g_free ((modulemd_nsvca *)nsvca); } G_DEFINE_AUTOPTR_CLEANUP_FUNC (modulemd_nsvca, modulemd_nsvca_free); static gboolean match_nsvca (gconstpointer haystraw, gconstpointer needle) { ModulemdModuleStream *stream = (ModulemdModuleStream *)haystraw; modulemd_nsvca *nsvca = (modulemd_nsvca *)needle; if (!g_str_equal (nsvca->stream_name, modulemd_module_stream_get_stream_name (stream))) { return FALSE; } if (nsvca->version) { if (nsvca->version != modulemd_module_stream_get_version (stream)) { return FALSE; } } if (nsvca->context) { if (!g_str_equal (nsvca->context, modulemd_module_stream_get_context (stream))) { return FALSE; } } if (nsvca->arch) { if (!g_str_equal (nsvca->arch, modulemd_module_stream_get_arch (stream))) { return FALSE; } } return TRUE; } void modulemd_module_remove_streams_by_NSVCA (ModulemdModule *self, const gchar *stream_name, const guint64 version, const gchar *context, const gchar *arch) { gboolean found = FALSE; guint index; g_autoptr (modulemd_nsvca) nsvca = g_malloc0_n (1, sizeof (modulemd_nsvca)); nsvca->stream_name = stream_name; nsvca->version = version; nsvca->context = context; nsvca->arch = arch; /* Iterate through the streams and remove any that match the requested * parameters */ do { found = g_ptr_array_find_with_equal_func ( self->streams, nsvca, match_nsvca, &index); if (found) { g_ptr_array_remove_index (self->streams, index); } } while (found); } void modulemd_module_add_translation (ModulemdModule *self, ModulemdTranslation *translation) { gsize i; ModulemdModuleStream *stream = NULL; ModulemdTranslation *newtrans = NULL; g_return_if_fail ( g_str_equal (modulemd_translation_get_module_name (translation), modulemd_module_get_module_name (self))); newtrans = modulemd_translation_copy (translation); g_hash_table_replace ( self->translations, g_strdup (modulemd_translation_get_module_stream (translation)), newtrans); for (i = 0; i < self->streams->len; i++) { stream = (ModulemdModuleStream *)g_ptr_array_index (self->streams, i); if (!g_str_equal (modulemd_translation_get_module_stream (newtrans), modulemd_module_stream_get_stream_name (stream))) { continue; } modulemd_module_stream_associate_translation (stream, newtrans); } } GPtrArray * modulemd_module_get_translated_streams (ModulemdModule *self) { return modulemd_ordered_str_keys (self->translations, modulemd_strcmp_sort); } ModulemdTranslation * modulemd_module_get_translation (ModulemdModule *self, const gchar *stream) { return g_hash_table_lookup (self->translations, stream); } void modulemd_module_add_obsoletes (ModulemdModule *self, ModulemdObsoletes *obsoletes) { gsize i; ModulemdModuleStream *stream = NULL; ModulemdObsoletes *new_obsoletes = NULL; ModulemdObsoletes *current_obsoletes = NULL; g_return_if_fail ( g_str_equal (modulemd_obsoletes_get_module_name (obsoletes), modulemd_module_get_module_name (self))); new_obsoletes = modulemd_obsoletes_copy (obsoletes); const gchar *stream_str = modulemd_obsoletes_get_module_stream (new_obsoletes); const gchar *context_str = modulemd_obsoletes_get_module_context (new_obsoletes); // First if we already have an obsolete with identical module, // stream, contex tand modified time override it ModulemdObsoletes *temp_obsoletes = NULL; for (guint j = 0; j < self->obsoletes->len; j++) { temp_obsoletes = g_ptr_array_index (self->obsoletes, j); if (g_strcmp0 (modulemd_obsoletes_get_module_stream (obsoletes), modulemd_obsoletes_get_module_stream (temp_obsoletes))) { continue; } if (modulemd_obsoletes_get_modified (temp_obsoletes) != modulemd_obsoletes_get_modified (obsoletes)) { continue; } if (g_strcmp0 (modulemd_obsoletes_get_module_context (obsoletes), modulemd_obsoletes_get_module_context (temp_obsoletes))) { continue; } g_info ( "Overriding existing obsolete because of identical stream: %s, " "context: %s and modified time: %" PRIu64 ".", modulemd_obsoletes_get_module_stream (obsoletes), modulemd_obsoletes_get_module_context (obsoletes), modulemd_obsoletes_get_modified (obsoletes)); g_ptr_array_remove (self->obsoletes, temp_obsoletes); break; } g_ptr_array_add (self->obsoletes, new_obsoletes); if (!modulemd_obsoletes_is_active (new_obsoletes)) { return; } for (i = 0; i < self->streams->len; i++) { stream = (ModulemdModuleStream *)g_ptr_array_index (self->streams, i); if (!g_str_equal (stream_str, modulemd_module_stream_get_stream_name (stream))) { continue; } /* If no context specified and new_obsoletes is newer set it for all matching * streams */ if (context_str) { if (g_strcmp0 (context_str, modulemd_module_stream_get_context (stream))) { continue; } } switch (modulemd_module_stream_get_mdversion (stream)) { case MD_MODULESTREAM_VERSION_TWO: current_obsoletes = modulemd_module_stream_v2_get_obsoletes ( (ModulemdModuleStreamV2 *)stream); break; default: g_info ( "ModuleStream obsoletes requires mdversion two or greater: " "module: %s, stream: %s, context: %s, mdversion: %u", modulemd_module_get_module_name (self), stream_str, context_str, (uint)modulemd_module_stream_get_mdversion (stream)); g_return_if_reached (); } if (current_obsoletes) { guint64 cur_obsoletes_mod = modulemd_obsoletes_get_modified (current_obsoletes); guint64 new_obsoletes_mod = modulemd_obsoletes_get_modified (new_obsoletes); if (cur_obsoletes_mod > new_obsoletes_mod) { continue; } else if (cur_obsoletes_mod == new_obsoletes_mod) { /* In case of identical modified dates, do not override more specific * obsoletes (obsoletes with context) with obsoletes without context. Otherwise override * with a warning. */ if (!context_str && modulemd_obsoletes_get_module_context (current_obsoletes)) { continue; } /* Print a warning only if both obsoletes (don't) have specified context */ else if (!context_str || modulemd_obsoletes_get_module_context ( current_obsoletes)) { g_info ( "Multiple obsoletes for module: %s, stream: %s, context: " "%s " "with identical modified time: %" PRIu64, modulemd_module_get_module_name (self), stream_str, context_str, new_obsoletes_mod); } } } switch (modulemd_module_stream_get_mdversion (stream)) { case MD_MODULESTREAM_VERSION_TWO: modulemd_module_stream_v2_associate_obsoletes ( (ModulemdModuleStreamV2 *)stream, new_obsoletes); break; default: /* Internal error */ g_info ( "ModuleStream obsoletes internal error: module: %s, stream: %s, " "context: %s, mdversion: %u", modulemd_module_get_module_name (self), stream_str, context_str, (uint)modulemd_module_stream_get_mdversion (stream)); g_return_if_reached (); } } } gboolean modulemd_module_upgrade_streams (ModulemdModule *self, ModulemdModuleStreamVersionEnum mdversion, GError **error) { g_autoptr (GPtrArray) new_streams = NULL; ModulemdModuleStreamVersionEnum current_mdversion; g_autoptr (ModulemdModuleStream) modulestream = NULL; g_autoptr (ModulemdModuleStream) upgraded_stream = NULL; g_autoptr (ModulemdModule) upgraded_module = NULL; GPtrArray *upgraded_streams = NULL; g_autofree gchar *nsvca = NULL; g_autoptr (GError) nested_error = NULL; g_return_val_if_fail (MODULEMD_IS_MODULE (self), FALSE); new_streams = g_ptr_array_new_full (self->streams->len, g_object_unref); for (guint i = 0; i < self->streams->len; i++) { modulestream = g_object_ref ( MODULEMD_MODULE_STREAM (g_ptr_array_index (self->streams, i))); current_mdversion = modulemd_module_stream_get_mdversion (modulestream); nsvca = modulemd_module_stream_get_NSVCA_as_string (modulestream); if (current_mdversion <= MD_MODULESTREAM_VERSION_UNSET) { g_set_error (error, MODULEMD_ERROR, MMD_ERROR_VALIDATE, "ModuleStream %s had invalid mdversion %i", nsvca, current_mdversion); return FALSE; } if (current_mdversion == mdversion) { /* Already at the right version, so just add it to the new list */ g_ptr_array_add (new_streams, g_steal_pointer (&modulestream)); } else { upgraded_module = modulemd_module_stream_upgrade_ext ( modulestream, mdversion, &nested_error); if (!upgraded_module) { g_propagate_prefixed_error (error, g_steal_pointer (&nested_error), "Error upgrading module stream %s", nsvca); return FALSE; } /* loop through all upgraded streams */ upgraded_streams = modulemd_module_get_all_streams (upgraded_module); for (guint i = 0; i < upgraded_streams->len; i++) { upgraded_stream = g_object_ref (g_ptr_array_index (upgraded_streams, i)); g_ptr_array_add (new_streams, g_steal_pointer (&upgraded_stream)); } g_clear_object (&upgraded_module); } g_clear_pointer (&nsvca, g_free); g_clear_object (&modulestream); } /* Replace the old stream list with the new one */ g_ptr_array_unref (self->streams); self->streams = g_steal_pointer (&new_streams); return TRUE; } GPtrArray * modulemd_module_get_obsoletes (ModulemdModule *self) { g_return_val_if_fail (MODULEMD_IS_MODULE (self), NULL); return self->obsoletes; } ModulemdObsoletes * modulemd_module_get_newest_active_obsoletes (ModulemdModule *self, const gchar *stream, const gchar *context) { ModulemdObsoletes *obsoletes = NULL; ModulemdObsoletes *newestActiveObsoletes = NULL; for (guint i = 0; i < self->obsoletes->len; i++) { obsoletes = (ModulemdObsoletes *)g_ptr_array_index (self->obsoletes, i); if (g_strcmp0 (modulemd_obsoletes_get_module_stream (obsoletes), stream) || g_strcmp0 (modulemd_obsoletes_get_module_context (obsoletes), context) || !modulemd_obsoletes_is_active (obsoletes)) { continue; } if (newestActiveObsoletes) { if (modulemd_obsoletes_get_modified (obsoletes) <= modulemd_obsoletes_get_modified (newestActiveObsoletes)) { continue; } } newestActiveObsoletes = obsoletes; } return newestActiveObsoletes; } static void clear_xmds (gpointer data, gpointer user_data) { g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (data)); modulemd_module_stream_v2_clear_xmd (MODULEMD_MODULE_STREAM_V2 (data)); } void modulemd_module_clear_xmds (ModulemdModule *self) { MODULEMD_INIT_TRACE (); g_return_if_fail (MODULEMD_IS_MODULE (self)); g_ptr_array_foreach (self->streams, clear_xmds, NULL); }