/* * This file is part of libmodulemd * Copyright (C) 2020 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 . */ #include "private/modulemd-build-config-private.h" #include "private/modulemd-component-private.h" #include "private/modulemd-component-module-private.h" #include "private/modulemd-component-rpm-private.h" #include "private/modulemd-defaults-v1-private.h" #include "private/modulemd-module-stream-private.h" #include "private/modulemd-packager-v3-private.h" #include "private/modulemd-profile-private.h" #include "private/modulemd-subdocument-info-private.h" #include "private/modulemd-util.h" #include "private/modulemd-yaml.h" struct _ModulemdPackagerV3 { GObject parent_instance; gchar *module_name; gchar *stream_name; gchar *summary; gchar *description; GHashTable *module_licenses; /* string set */ GVariant *xmd; GHashTable *build_configs; /* */ gchar *community; gchar *documentation; gchar *tracker; GHashTable *profiles; /* */ GHashTable *rpm_api; /* string set */ GHashTable *rpm_filters; /* string set */ GHashTable *demodularized_rpms; /* string set */ GHashTable *rpm_components; /* */ GHashTable *module_components; /* module_name, g_free); g_clear_pointer (&self->stream_name, g_free); g_clear_pointer (&self->summary, g_free); g_clear_pointer (&self->description, g_free); g_clear_pointer (&self->module_licenses, g_hash_table_unref); g_clear_pointer (&self->xmd, g_variant_unref); g_clear_pointer (&self->build_configs, g_hash_table_unref); g_clear_pointer (&self->community, g_free); g_clear_pointer (&self->documentation, g_free); g_clear_pointer (&self->tracker, g_free); g_clear_pointer (&self->profiles, g_hash_table_unref); g_clear_pointer (&self->rpm_api, g_hash_table_unref); g_clear_pointer (&self->rpm_filters, g_hash_table_unref); g_clear_pointer (&self->demodularized_rpms, g_hash_table_unref); g_clear_pointer (&self->rpm_components, g_hash_table_unref); g_clear_pointer (&self->module_components, g_hash_table_unref); G_OBJECT_CLASS (modulemd_packager_v3_parent_class)->finalize (object); } static void modulemd_packager_v3_class_init (ModulemdPackagerV3Class *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = modulemd_packager_v3_finalize; } static void modulemd_packager_v3_init (ModulemdPackagerV3 *self) { self->module_licenses = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); self->build_configs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); self->profiles = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); self->rpm_api = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); self->rpm_filters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); self->demodularized_rpms = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); self->rpm_components = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); self->module_components = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); } ModulemdPackagerV3 * modulemd_packager_v3_copy (ModulemdPackagerV3 *self) { g_autoptr (ModulemdPackagerV3) copy = modulemd_packager_v3_new (); modulemd_packager_v3_set_module_name ( copy, modulemd_packager_v3_get_module_name (self)); modulemd_packager_v3_set_stream_name ( copy, modulemd_packager_v3_get_stream_name (self)); modulemd_packager_v3_set_summary (copy, modulemd_packager_v3_get_summary (self)); modulemd_packager_v3_set_description ( copy, modulemd_packager_v3_get_description (self)); MODULEMD_REPLACE_SET (copy->module_licenses, self->module_licenses); modulemd_packager_v3_set_xmd (copy, modulemd_packager_v3_get_xmd (self)); COPY_HASHTABLE_BY_VALUE_ADDER ( copy, self, build_configs, modulemd_packager_v3_add_build_config); modulemd_packager_v3_set_community ( copy, modulemd_packager_v3_get_community (self)); modulemd_packager_v3_set_documentation ( copy, modulemd_packager_v3_get_documentation (self)); modulemd_packager_v3_set_tracker (copy, modulemd_packager_v3_get_tracker (self)); COPY_HASHTABLE_BY_VALUE_ADDER ( copy, self, profiles, modulemd_packager_v3_add_profile); modulemd_packager_v3_replace_rpm_api (copy, self->rpm_api); modulemd_packager_v3_replace_rpm_filters (copy, self->rpm_filters); modulemd_packager_v3_replace_demodularized_rpms (copy, self->demodularized_rpms); COPY_HASHTABLE_BY_VALUE_ADDER ( copy, self, rpm_components, modulemd_packager_v3_add_component); COPY_HASHTABLE_BY_VALUE_ADDER ( copy, self, module_components, modulemd_packager_v3_add_component); return g_steal_pointer (©); } void modulemd_packager_v3_set_module_name (ModulemdPackagerV3 *self, const gchar *module_name) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_clear_pointer (&self->module_name, g_free); if (module_name) { self->module_name = g_strdup (module_name); } } const gchar * modulemd_packager_v3_get_module_name (ModulemdPackagerV3 *self) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return self->module_name; } void modulemd_packager_v3_set_stream_name (ModulemdPackagerV3 *self, const gchar *stream_name) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_clear_pointer (&self->stream_name, g_free); if (stream_name) { self->stream_name = g_strdup (stream_name); } } const gchar * modulemd_packager_v3_get_stream_name (ModulemdPackagerV3 *self) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return self->stream_name; } void modulemd_packager_v3_set_summary (ModulemdPackagerV3 *self, const gchar *summary) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_clear_pointer (&self->summary, g_free); if (summary) { self->summary = g_strdup (summary); } } const gchar * modulemd_packager_v3_get_summary (ModulemdPackagerV3 *self) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return self->summary; } void modulemd_packager_v3_set_description (ModulemdPackagerV3 *self, const gchar *description) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_clear_pointer (&self->description, g_free); if (description) { self->description = g_strdup (description); } } const gchar * modulemd_packager_v3_get_description (ModulemdPackagerV3 *self) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return self->description; } void modulemd_packager_v3_add_module_license (ModulemdPackagerV3 *self, const gchar *license) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); if (!license) { return; } g_hash_table_add (self->module_licenses, g_strdup (license)); } void modulemd_packager_v3_remove_module_license (ModulemdPackagerV3 *self, const gchar *license) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); if (!license) { return; } g_hash_table_remove (self->module_licenses, license); } void modulemd_packager_v3_clear_module_licenses (ModulemdPackagerV3 *self) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_hash_table_remove_all (self->module_licenses); } GStrv modulemd_packager_v3_get_module_licenses_as_strv (ModulemdPackagerV3 *self) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return modulemd_ordered_str_keys_as_strv (self->module_licenses); } void modulemd_packager_v3_set_xmd (ModulemdPackagerV3 *self, GVariant *xmd) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); /* Do nothing if we were passed the same pointer */ if (self->xmd == xmd) { return; } g_clear_pointer (&self->xmd, g_variant_unref); self->xmd = modulemd_variant_deep_copy (xmd); } GVariant * modulemd_packager_v3_get_xmd (ModulemdPackagerV3 *self) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return self->xmd; } guint64 modulemd_packager_v3_get_mdversion (ModulemdPackagerV3 *self) { return MD_PACKAGER_VERSION_THREE; } void modulemd_packager_v3_add_build_config (ModulemdPackagerV3 *self, ModulemdBuildConfig *buildconfig) { if (!buildconfig) return; g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_return_if_fail (MODULEMD_IS_BUILD_CONFIG (buildconfig)); g_hash_table_replace ( self->build_configs, g_strdup (modulemd_build_config_get_context (buildconfig)), modulemd_build_config_copy (buildconfig)); } void modulemd_packager_v3_clear_build_configs (ModulemdPackagerV3 *self) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_hash_table_remove_all (self->build_configs); } GStrv modulemd_packager_v3_get_build_config_contexts_as_strv ( ModulemdPackagerV3 *self) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return modulemd_ordered_str_keys_as_strv (self->build_configs); } ModulemdBuildConfig * modulemd_packager_v3_get_build_config (ModulemdPackagerV3 *self, const gchar *context) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return g_hash_table_lookup (self->build_configs, context); } void modulemd_packager_v3_set_community (ModulemdPackagerV3 *self, const gchar *community) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_clear_pointer (&self->community, g_free); if (community) { self->community = g_strdup (community); } } const gchar * modulemd_packager_v3_get_community (ModulemdPackagerV3 *self) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return self->community; } void modulemd_packager_v3_set_documentation (ModulemdPackagerV3 *self, const gchar *documentation) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_clear_pointer (&self->documentation, g_free); if (documentation) { self->documentation = g_strdup (documentation); } } const gchar * modulemd_packager_v3_get_documentation (ModulemdPackagerV3 *self) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return self->documentation; } void modulemd_packager_v3_set_tracker (ModulemdPackagerV3 *self, const gchar *tracker) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_clear_pointer (&self->tracker, g_free); if (tracker) { self->tracker = g_strdup (tracker); } } const gchar * modulemd_packager_v3_get_tracker (ModulemdPackagerV3 *self) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return self->tracker; } void modulemd_packager_v3_add_profile (ModulemdPackagerV3 *self, ModulemdProfile *profile) { if (!profile) { return; } g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_return_if_fail (MODULEMD_IS_PROFILE (profile)); ModulemdProfile *copied_profile = modulemd_profile_copy (profile); g_hash_table_replace (self->profiles, g_strdup (modulemd_profile_get_name (profile)), copied_profile); } void modulemd_packager_v3_clear_profiles (ModulemdPackagerV3 *self) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_hash_table_remove_all (self->profiles); } GStrv modulemd_packager_v3_get_profile_names_as_strv (ModulemdPackagerV3 *self) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return modulemd_ordered_str_keys_as_strv (self->profiles); } ModulemdProfile * modulemd_packager_v3_get_profile (ModulemdPackagerV3 *self, const gchar *profile_name) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return g_hash_table_lookup (self->profiles, profile_name); } void modulemd_packager_v3_add_rpm_api (ModulemdPackagerV3 *self, const gchar *rpm) { if (!rpm) { return; } g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_hash_table_add (self->rpm_api, g_strdup (rpm)); } void modulemd_packager_v3_replace_rpm_api (ModulemdPackagerV3 *self, GHashTable *set) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); MODULEMD_REPLACE_SET (self->rpm_api, set); } void modulemd_packager_v3_remove_rpm_api (ModulemdPackagerV3 *self, const gchar *rpm) { if (!rpm) { return; } g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_hash_table_remove (self->rpm_api, rpm); } void modulemd_packager_v3_clear_rpm_api (ModulemdPackagerV3 *self) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_hash_table_remove_all (self->rpm_api); } GStrv modulemd_packager_v3_get_rpm_api_as_strv (ModulemdPackagerV3 *self) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return modulemd_ordered_str_keys_as_strv (self->rpm_api); } void modulemd_packager_v3_add_rpm_filter (ModulemdPackagerV3 *self, const gchar *rpm) { if (!rpm) { return; } g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_hash_table_add (self->rpm_filters, g_strdup (rpm)); } void modulemd_packager_v3_replace_rpm_filters (ModulemdPackagerV3 *self, GHashTable *set) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); MODULEMD_REPLACE_SET (self->rpm_filters, set); } void modulemd_packager_v3_remove_rpm_filter (ModulemdPackagerV3 *self, const gchar *rpm) { if (!rpm) { return; } g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_hash_table_remove (self->rpm_filters, rpm); } void modulemd_packager_v3_clear_rpm_filters (ModulemdPackagerV3 *self) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_hash_table_remove_all (self->rpm_filters); } GStrv modulemd_packager_v3_get_rpm_filters_as_strv (ModulemdPackagerV3 *self) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return modulemd_ordered_str_keys_as_strv (self->rpm_filters); } void modulemd_packager_v3_add_demodularized_rpm (ModulemdPackagerV3 *self, const gchar *rpm) { if (!rpm) { return; } g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_hash_table_add (self->demodularized_rpms, g_strdup (rpm)); } void modulemd_packager_v3_replace_demodularized_rpms (ModulemdPackagerV3 *self, GHashTable *set) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); MODULEMD_REPLACE_SET (self->demodularized_rpms, set); } void modulemd_packager_v3_remove_demodularized_rpm (ModulemdPackagerV3 *self, const gchar *rpm) { if (!rpm) { return; } g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_hash_table_remove (self->demodularized_rpms, rpm); } void modulemd_packager_v3_clear_demodularized_rpms (ModulemdPackagerV3 *self) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_hash_table_remove_all (self->demodularized_rpms); } GStrv modulemd_packager_v3_get_demodularized_rpms (ModulemdPackagerV3 *self) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return modulemd_ordered_str_keys_as_strv (self->demodularized_rpms); } void modulemd_packager_v3_add_component (ModulemdPackagerV3 *self, ModulemdComponent *component) { GHashTable *table = NULL; /* Do nothing if we were passed a NULL component */ if (!component) { return; } g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_return_if_fail (MODULEMD_IS_COMPONENT (component)); if (MODULEMD_IS_COMPONENT_RPM (component)) { table = self->rpm_components; } else if (MODULEMD_IS_COMPONENT_MODULE (component)) { table = self->module_components; } else { /* Unknown component. Raise a warning and return */ g_return_if_reached (); } /* Add the component to the table. This will replace an existing component * with the same name */ g_hash_table_replace (table, g_strdup (modulemd_component_get_key (component)), modulemd_component_copy (component, NULL)); } void modulemd_packager_v3_remove_module_component (ModulemdPackagerV3 *self, const gchar *component_name) { /* Do nothing if we were passed a NULL component_name */ if (!component_name) { return; } g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_hash_table_remove (self->module_components, component_name); } void modulemd_packager_v3_clear_module_components (ModulemdPackagerV3 *self) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_hash_table_remove_all (self->module_components); } void modulemd_packager_v3_remove_rpm_component (ModulemdPackagerV3 *self, const gchar *component_name) { /* Do nothing if we were passed a NULL component_name */ if (!component_name) { return; } g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_hash_table_remove (self->rpm_components, component_name); } void modulemd_packager_v3_clear_rpm_components (ModulemdPackagerV3 *self) { g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self)); g_hash_table_remove_all (self->rpm_components); } GStrv modulemd_packager_v3_get_module_component_names_as_strv ( ModulemdPackagerV3 *self) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return modulemd_ordered_str_keys_as_strv (self->module_components); } GStrv modulemd_packager_v3_get_rpm_component_names_as_strv (ModulemdPackagerV3 *self) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return modulemd_ordered_str_keys_as_strv (self->rpm_components); } ModulemdComponentModule * modulemd_packager_v3_get_module_component (ModulemdPackagerV3 *self, const gchar *component_name) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return g_hash_table_lookup (self->module_components, component_name); } ModulemdComponentRpm * modulemd_packager_v3_get_rpm_component (ModulemdPackagerV3 *self, const gchar *component_name) { g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); return g_hash_table_lookup (self->rpm_components, component_name); } gboolean modulemd_packager_v3_to_defaults (ModulemdPackagerV3 *self, ModulemdDefaults **defaults_ptr, GError **error) { g_autoptr (ModulemdDefaultsV1) defaults = NULL; ModulemdProfile *profile; g_autoptr (GError) nested_error = NULL; GHashTableIter iter; gpointer value; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); g_return_val_if_fail (defaults_ptr == NULL || *defaults_ptr == NULL, FALSE); g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), FALSE); g_hash_table_iter_init (&iter, self->profiles); while (g_hash_table_iter_next (&iter, NULL, &value)) { profile = MODULEMD_PROFILE (value); if (modulemd_profile_is_default (profile)) { if (!defaults) { defaults = modulemd_defaults_v1_new (self->module_name); } modulemd_defaults_v1_add_default_profile_for_stream ( defaults, self->stream_name, modulemd_profile_get_name (profile), NULL); } } if (!defaults) { return TRUE; } if (!modulemd_defaults_validate (MODULEMD_DEFAULTS (defaults), &nested_error)) { g_propagate_error (error, g_steal_pointer (&nested_error)); return FALSE; } *defaults_ptr = MODULEMD_DEFAULTS (g_steal_pointer (&defaults)); return TRUE; } static void copy_packager_v3_common_to_stream_v2 (ModulemdModuleStreamV2 *stream_v2, ModulemdPackagerV3 *packager_v3) { g_autoptr (ModulemdProfile) profile = NULL; GHashTableIter iter; gpointer value; modulemd_module_stream_v2_set_summary ( stream_v2, modulemd_packager_v3_get_summary (packager_v3)); modulemd_module_stream_v2_set_description ( stream_v2, modulemd_packager_v3_get_description (packager_v3)); /* Packager v3 "license" is optional. Stream v2 "license" is required * Fill in the default Packager v3 license if none has been specified. */ if (g_hash_table_size (packager_v3->module_licenses) == 0) { modulemd_module_stream_v2_add_module_license ( stream_v2, MMD_PACKAGER_DEFAULT_MODULE_LICENSE); } else { MODULEMD_REPLACE_SET (stream_v2->module_licenses, packager_v3->module_licenses); } modulemd_module_stream_v2_set_xmd ( stream_v2, modulemd_packager_v3_get_xmd (packager_v3)); modulemd_module_stream_v2_set_community ( stream_v2, modulemd_packager_v3_get_community (packager_v3)); modulemd_module_stream_v2_set_documentation ( stream_v2, modulemd_packager_v3_get_documentation (packager_v3)); modulemd_module_stream_v2_set_tracker ( stream_v2, modulemd_packager_v3_get_tracker (packager_v3)); g_hash_table_iter_init (&iter, packager_v3->profiles); while (g_hash_table_iter_next (&iter, NULL, &value)) { profile = modulemd_profile_copy (MODULEMD_PROFILE (value)); modulemd_profile_unset_default (profile); modulemd_module_stream_v2_add_profile (stream_v2, profile); g_clear_object (&profile); } modulemd_module_stream_v2_replace_rpm_api (stream_v2, packager_v3->rpm_api); modulemd_module_stream_v2_replace_rpm_filters (stream_v2, packager_v3->rpm_filters); modulemd_module_stream_v2_replace_demodularized_rpms ( stream_v2, packager_v3->demodularized_rpms); COPY_HASHTABLE_BY_VALUE_ADDER (stream_v2, packager_v3, rpm_components, modulemd_module_stream_v2_add_component); COPY_HASHTABLE_BY_VALUE_ADDER (stream_v2, packager_v3, module_components, modulemd_module_stream_v2_add_component); } static void copy_packager_v3_buildconfig_to_stream_v2 (ModulemdModuleStreamV2 *stream_v2, ModulemdBuildConfig *bc) { g_autoptr (ModulemdDependencies) deps = NULL; g_auto (GStrv) modules = NULL; modulemd_module_stream_v2_set_buildopts ( stream_v2, modulemd_build_config_get_buildopts (bc)); deps = modulemd_dependencies_new (); modulemd_dependencies_add_buildtime_stream ( deps, "platform", modulemd_build_config_get_platform (bc)); modulemd_dependencies_add_runtime_stream ( deps, "platform", modulemd_build_config_get_platform (bc)); modules = modulemd_build_config_get_buildtime_modules_as_strv (bc); for (guint j = 0; j < g_strv_length (modules); j++) { modulemd_dependencies_add_buildtime_stream ( deps, modules[j], modulemd_build_config_get_buildtime_requirement_stream (bc, modules[j])); } g_clear_pointer (&modules, g_strfreev); modules = modulemd_build_config_get_runtime_modules_as_strv (bc); for (guint j = 0; j < g_strv_length (modules); j++) { modulemd_dependencies_add_runtime_stream ( deps, modules[j], modulemd_build_config_get_runtime_requirement_stream (bc, modules[j])); } g_clear_pointer (&modules, g_strfreev); modulemd_module_stream_v2_add_dependencies (stream_v2, deps); g_clear_object (&deps); } ModulemdModuleStreamV2 * modulemd_packager_v3_to_stream_v2 (ModulemdPackagerV3 *self, GError **error) { g_autoptr (ModulemdModuleStreamV2) v2_stream = NULL; g_auto (GStrv) contexts = NULL; g_autoptr (GError) nested_error = NULL; ModulemdBuildopts *buildopts = NULL; ModulemdBuildConfig *bc; g_return_val_if_fail (error == NULL || *error == NULL, NULL); g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); v2_stream = modulemd_module_stream_v2_new ( modulemd_packager_v3_get_module_name (self), modulemd_packager_v3_get_stream_name (self)); /* set attributes that are the same for all streams */ copy_packager_v3_common_to_stream_v2 (v2_stream, self); /* get the list of packager build configuration contexts */ contexts = modulemd_packager_v3_get_build_config_contexts_as_strv (self); /* If there is exactly one build configuration, use it for the stream */ /* context. Otherwise, leave the stream context unset. */ if (g_strv_length (contexts) == 1) { modulemd_module_stream_set_context (MODULEMD_MODULE_STREAM (v2_stream), contexts[0]); } /* map each BuildConfig object to a Dependencies object within the same StreamV2 object */ for (guint i = 0; i < g_strv_length (contexts); i++) { bc = modulemd_packager_v3_get_build_config (self, contexts[i]); if (i == 0) { /* Save the buildopts from the first build configuration to */ /* set the stream buildopts. */ buildopts = modulemd_build_config_get_buildopts (bc); } /* set attributes that are unique per build configuration */ copy_packager_v3_buildconfig_to_stream_v2 (v2_stream, bc); } g_clear_pointer (&contexts, g_strfreev); /* set the saved buildopts from the first build configuration */ modulemd_module_stream_v2_set_buildopts (v2_stream, buildopts); if (!modulemd_module_stream_validate (MODULEMD_MODULE_STREAM (v2_stream), &nested_error)) { g_propagate_error (error, g_steal_pointer (&nested_error)); return NULL; } return g_steal_pointer (&v2_stream); } ModulemdModuleIndex * modulemd_packager_v3_to_stream_v2_ext (ModulemdPackagerV3 *self, GError **error) { g_autoptr (ModulemdModuleIndex) index = NULL; g_autoptr (ModulemdModuleStreamV2) v2_stream = NULL; g_autoptr (ModulemdDefaults) defaults = NULL; g_autoptr (GError) nested_error = NULL; g_return_val_if_fail (error == NULL || *error == NULL, NULL); g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); v2_stream = modulemd_packager_v3_to_stream_v2 (self, &nested_error); if (!v2_stream) { g_propagate_error (error, g_steal_pointer (&nested_error)); return NULL; } /* autogen module/stream names if necessary for adding to index */ modulemd_module_stream_set_autogen_module_name ( MODULEMD_MODULE_STREAM (v2_stream), 0); modulemd_module_stream_set_autogen_stream_name ( MODULEMD_MODULE_STREAM (v2_stream), 0); index = modulemd_module_index_new (); if (!modulemd_module_index_add_module_stream ( index, MODULEMD_MODULE_STREAM (v2_stream), &nested_error)) { g_propagate_error (error, g_steal_pointer (&nested_error)); return NULL; } g_clear_object (&v2_stream); if (!modulemd_packager_v3_to_defaults (self, &defaults, &nested_error)) { g_propagate_error (error, g_steal_pointer (&nested_error)); return NULL; } if (defaults) { if (!modulemd_module_index_add_defaults (index, defaults, &nested_error)) { g_propagate_error (error, g_steal_pointer (&nested_error)); return NULL; } g_clear_object (&defaults); } return g_steal_pointer (&index); } ModulemdModuleIndex * modulemd_packager_v3_convert_to_index (ModulemdPackagerV3 *self, GError **error) { g_auto (GStrv) contexts = NULL; g_autoptr (ModulemdModuleIndex) index = NULL; g_autoptr (ModulemdModuleStreamV2) v2_stream = NULL; g_autoptr (ModulemdDefaults) defaults = NULL; g_autoptr (GError) nested_error = NULL; ModulemdBuildConfig *bc; g_return_val_if_fail (error == NULL || *error == NULL, NULL); g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL); /* get the list of packager build configuration contexts */ contexts = modulemd_packager_v3_get_build_config_contexts_as_strv (self); if (g_strv_length (contexts) == 0) { g_set_error_literal (error, MODULEMD_ERROR, MMD_ERROR_VALIDATE, "Packager document with no build configurations " "cannot be converted to stream"); return NULL; } /* create a ModuleIndex to contain the results */ index = modulemd_module_index_new (); /* create a StreamV2 object for each BuildConfig object */ for (guint i = 0; i < g_strv_length (contexts); i++) { bc = modulemd_packager_v3_get_build_config (self, contexts[i]); v2_stream = modulemd_module_stream_v2_new ( modulemd_packager_v3_get_module_name (self), modulemd_packager_v3_get_stream_name (self)); modulemd_module_stream_set_context (MODULEMD_MODULE_STREAM (v2_stream), contexts[i]); /* set attributes that are the same for all streams */ copy_packager_v3_common_to_stream_v2 (v2_stream, self); /* set attributes that are unique per build configuration */ copy_packager_v3_buildconfig_to_stream_v2 (v2_stream, bc); if (!modulemd_module_stream_validate (MODULEMD_MODULE_STREAM (v2_stream), &nested_error)) { g_propagate_error (error, g_steal_pointer (&nested_error)); return NULL; } /* autogen module/stream names if necessary for adding to index */ modulemd_module_stream_set_autogen_module_name ( MODULEMD_MODULE_STREAM (v2_stream), 0); modulemd_module_stream_set_autogen_stream_name ( MODULEMD_MODULE_STREAM (v2_stream), 0); if (!modulemd_module_index_add_module_stream ( index, MODULEMD_MODULE_STREAM (v2_stream), &nested_error)) { g_propagate_error (error, g_steal_pointer (&nested_error)); return NULL; } g_clear_object (&v2_stream); } g_clear_pointer (&contexts, g_strfreev); if (!modulemd_packager_v3_to_defaults (self, &defaults, &nested_error)) { g_propagate_error (error, g_steal_pointer (&nested_error)); return NULL; } if (defaults) { if (!modulemd_module_index_add_defaults (index, defaults, &nested_error)) { g_propagate_error (error, g_steal_pointer (&nested_error)); return NULL; } g_clear_object (&defaults); } return g_steal_pointer (&index); } static gboolean modulemd_packager_v3_parse_build_configs (yaml_parser_t *parser, ModulemdPackagerV3 *packager, gboolean strict, GError **error); static gboolean modulemd_packager_v3_parse_refs (yaml_parser_t *parser, ModulemdPackagerV3 *packager, gboolean strict, GError **error); static gboolean modulemd_packager_v3_parse_profiles (yaml_parser_t *parser, ModulemdPackagerV3 *packager, gboolean strict, GError **error); static gboolean modulemd_packager_v3_parse_components (yaml_parser_t *parser, ModulemdPackagerV3 *packager, gboolean strict, GError **error); ModulemdPackagerV3 * modulemd_packager_v3_parse_yaml (ModulemdSubdocumentInfo *subdoc, GError **error) { MODULEMD_INIT_TRACE (); MMD_INIT_YAML_PARSER (parser); MMD_INIT_YAML_EVENT (event); gboolean done = FALSE; const gboolean strict = TRUE; /* PackagerV3 should always parse strictly */ g_autoptr (GError) nested_error = NULL; g_autoptr (ModulemdPackagerV3) packager = NULL; g_autoptr (GHashTable) set = NULL; g_autoptr (GVariant) xmd = NULL; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); if (!modulemd_subdocument_info_get_data_parser ( subdoc, &parser, strict, error)) { return FALSE; } packager = modulemd_packager_v3_new (); /* Read the MAPPING_START */ YAML_PARSER_PARSE_WITH_EXIT (&parser, &event, error); if (event.type != YAML_MAPPING_START_EVENT) { MMD_YAML_ERROR_EVENT_EXIT ( error, event, "Data section did not begin with a map."); } /* Process through the mapping */ 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: /* Mapping Keys */ if (g_str_equal ((const gchar *)event.data.scalar.value, "name")) { MMD_SET_PARSED_YAML_STRING (&parser, error, modulemd_packager_v3_set_module_name, packager); } else if (g_str_equal ((const gchar *)event.data.scalar.value, "stream")) { MMD_SET_PARSED_YAML_STRING (&parser, error, modulemd_packager_v3_set_stream_name, packager); } else if (g_str_equal ((const gchar *)event.data.scalar.value, "summary")) { MMD_SET_PARSED_YAML_STRING ( &parser, error, modulemd_packager_v3_set_summary, packager); } else if (g_str_equal ((const gchar *)event.data.scalar.value, "description")) { MMD_SET_PARSED_YAML_STRING (&parser, error, modulemd_packager_v3_set_description, packager); } else if (g_str_equal ((const gchar *)event.data.scalar.value, "license")) { set = modulemd_yaml_parse_string_set (&parser, &nested_error); MODULEMD_REPLACE_SET (packager->module_licenses, set); g_clear_pointer (&set, g_hash_table_unref); } else if (g_str_equal ((const gchar *)event.data.scalar.value, "xmd")) { xmd = mmd_parse_xmd (&parser, &nested_error); if (!xmd) { g_propagate_error (error, g_steal_pointer (&nested_error)); return NULL; } modulemd_packager_v3_set_xmd (packager, xmd); g_clear_pointer (&xmd, g_variant_unref); } else if (g_str_equal ((const gchar *)event.data.scalar.value, "configurations")) { if (!modulemd_packager_v3_parse_build_configs ( &parser, packager, strict, &nested_error)) { g_propagate_error (error, g_steal_pointer (&nested_error)); return NULL; } } else if (g_str_equal ((const gchar *)event.data.scalar.value, "references")) { if (!modulemd_packager_v3_parse_refs ( &parser, packager, strict, &nested_error)) { g_propagate_error (error, g_steal_pointer (&nested_error)); return NULL; } } else if (g_str_equal ((const gchar *)event.data.scalar.value, "profiles")) { if (!modulemd_packager_v3_parse_profiles ( &parser, packager, strict, &nested_error)) { g_propagate_error (error, g_steal_pointer (&nested_error)); return NULL; } } else if (g_str_equal ((const gchar *)event.data.scalar.value, "api")) { set = modulemd_yaml_parse_string_set_from_map ( &parser, "rpms", strict, &nested_error); modulemd_packager_v3_replace_rpm_api (packager, set); g_clear_pointer (&set, g_hash_table_unref); } else if (g_str_equal ((const gchar *)event.data.scalar.value, "filter")) { set = modulemd_yaml_parse_string_set_from_map ( &parser, "rpms", strict, &nested_error); modulemd_packager_v3_replace_rpm_filters (packager, set); g_clear_pointer (&set, g_hash_table_unref); } else if (g_str_equal ((const gchar *)event.data.scalar.value, "demodularized")) { set = modulemd_yaml_parse_string_set_from_map ( &parser, "rpms", strict, &nested_error); modulemd_packager_v3_replace_demodularized_rpms (packager, set); g_clear_pointer (&set, g_hash_table_unref); } else if (g_str_equal ((const gchar *)event.data.scalar.value, "components")) { if (!modulemd_packager_v3_parse_components ( &parser, packager, strict, &nested_error)) { g_propagate_error (error, g_steal_pointer (&nested_error)); return NULL; } } else { SKIP_UNKNOWN (&parser, NULL, "Unexpected key in packager v3 document: %s", (const gchar *)event.data.scalar.value); break; } break; default: MMD_YAML_ERROR_EVENT_EXIT ( error, event, "Unexpected YAML event in ModuleStreamV2: %s", mmd_yaml_get_event_name (event.type)); break; } yaml_event_delete (&event); } return g_steal_pointer (&packager); } static gboolean modulemd_packager_v3_parse_build_configs (yaml_parser_t *parser, ModulemdPackagerV3 *packager, gboolean strict, GError **error) { MMD_INIT_YAML_EVENT (event); gboolean done = FALSE; g_autoptr (ModulemdBuildConfig) buildconfig = NULL; g_autoptr (GError) nested_error = NULL; YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error); if (event.type != YAML_SEQUENCE_START_EVENT) { MMD_YAML_ERROR_EVENT_EXIT_BOOL ( error, event, "Unexpected YAML event in build_configs"); } while (!done) { YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error); switch (event.type) { case YAML_SEQUENCE_END_EVENT: done = TRUE; break; case YAML_MAPPING_START_EVENT: buildconfig = modulemd_build_config_parse_yaml (parser, strict, &nested_error); if (!buildconfig) { g_propagate_error (error, g_steal_pointer (&nested_error)); return FALSE; } modulemd_packager_v3_add_build_config (packager, buildconfig); g_clear_object (&buildconfig); break; default: MMD_YAML_ERROR_EVENT_EXIT_BOOL ( error, event, "Unexpected YAML event in build_config list"); break; } yaml_event_delete (&event); } return TRUE; } static gboolean modulemd_packager_v3_parse_refs (yaml_parser_t *parser, ModulemdPackagerV3 *packager, gboolean strict, GError **error) { MODULEMD_INIT_TRACE (); MMD_INIT_YAML_EVENT (event); gboolean done = FALSE; g_autofree gchar *scalar = NULL; g_autoptr (GError) nested_error = NULL; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); /* Process through the map */ /* We *must* get a MAPPING_START here */ YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error); if (event.type != YAML_MAPPING_START_EVENT) { MMD_YAML_ERROR_EVENT_EXIT_BOOL ( error, event, "Got %s instead of MAPPING_START in references.", mmd_yaml_get_event_name (event.type)); } while (!done) { YAML_PARSER_PARSE_WITH_EXIT_BOOL (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, "community")) { scalar = modulemd_yaml_parse_string (parser, &nested_error); if (!scalar) { g_propagate_error (error, g_steal_pointer (&nested_error)); return FALSE; } modulemd_packager_v3_set_community (packager, scalar); g_clear_pointer (&scalar, g_free); } else if (g_str_equal ((const gchar *)event.data.scalar.value, "documentation")) { scalar = modulemd_yaml_parse_string (parser, &nested_error); if (!scalar) { g_propagate_error (error, g_steal_pointer (&nested_error)); return FALSE; } modulemd_packager_v3_set_documentation (packager, scalar); g_clear_pointer (&scalar, g_free); } else if (g_str_equal ((const gchar *)event.data.scalar.value, "tracker")) { scalar = modulemd_yaml_parse_string (parser, &nested_error); if (!scalar) { g_propagate_error (error, g_steal_pointer (&nested_error)); return FALSE; } modulemd_packager_v3_set_tracker (packager, scalar); g_clear_pointer (&scalar, g_free); } else { SKIP_UNKNOWN (parser, FALSE, "Unexpected key in references: %s", (const gchar *)event.data.scalar.value); break; } break; default: MMD_YAML_ERROR_EVENT_EXIT_BOOL ( error, event, "Unexpected YAML event in references: %s", mmd_yaml_get_event_name (event.type)); break; } yaml_event_delete (&event); } return TRUE; } static gboolean modulemd_packager_v3_parse_profiles (yaml_parser_t *parser, ModulemdPackagerV3 *packager, gboolean strict, GError **error) { MODULEMD_INIT_TRACE (); MMD_INIT_YAML_EVENT (event); gboolean done = FALSE; g_autoptr (GError) nested_error = NULL; g_autoptr (ModulemdProfile) profile = NULL; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); /* Process through the map */ /* We *must* get a MAPPING_START here */ YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error); if (event.type != YAML_MAPPING_START_EVENT) { MMD_YAML_ERROR_EVENT_EXIT_BOOL ( error, event, "Got %s instead of MAPPING_START in profiles.", mmd_yaml_get_event_name (event.type)); } while (!done) { YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error); switch (event.type) { case YAML_MAPPING_END_EVENT: done = TRUE; break; case YAML_SCALAR_EVENT: profile = modulemd_profile_parse_yaml ( parser, (const gchar *)event.data.scalar.value, strict, &nested_error); if (!profile) { g_propagate_error (error, g_steal_pointer (&nested_error)); return FALSE; } modulemd_packager_v3_add_profile (packager, profile); g_clear_pointer (&profile, g_object_unref); break; default: MMD_YAML_ERROR_EVENT_EXIT_BOOL ( error, event, "Unexpected YAML event in profiles: %s", mmd_yaml_get_event_name (event.type)); break; } yaml_event_delete (&event); } return TRUE; } static gboolean modulemd_packager_v3_parse_rpm_components (yaml_parser_t *parser, ModulemdPackagerV3 *packager, gboolean strict, GError **error); static gboolean modulemd_packager_v3_parse_module_components (yaml_parser_t *parser, ModulemdPackagerV3 *packager, gboolean strict, GError **error); static gboolean modulemd_packager_v3_parse_components (yaml_parser_t *parser, ModulemdPackagerV3 *packager, gboolean strict, GError **error) { MODULEMD_INIT_TRACE (); MMD_INIT_YAML_EVENT (event); gboolean done = FALSE; g_autoptr (GError) nested_error = NULL; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); /* Process through the sequence */ /* We *must* get a MAPPING_START here */ YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error); if (event.type != YAML_MAPPING_START_EVENT) { MMD_YAML_ERROR_EVENT_EXIT_BOOL ( error, event, "Got %s instead of MAPPING_START in components.", mmd_yaml_get_event_name (event.type)); } while (!done) { YAML_PARSER_PARSE_WITH_EXIT_BOOL (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, "rpms")) { if (!modulemd_packager_v3_parse_rpm_components ( parser, packager, strict, &nested_error)) { g_propagate_error (error, g_steal_pointer (&nested_error)); return FALSE; } } else if (g_str_equal ((const gchar *)event.data.scalar.value, "modules")) { if (!modulemd_packager_v3_parse_module_components ( parser, packager, strict, &nested_error)) { g_propagate_error (error, g_steal_pointer (&nested_error)); return FALSE; } } else { SKIP_UNKNOWN (parser, FALSE, "Unexpected key in components: %s", (const gchar *)event.data.scalar.value); } break; default: MMD_YAML_ERROR_EVENT_EXIT_BOOL ( error, event, "Unexpected YAML event in components: %s", mmd_yaml_get_event_name (event.type)); break; } yaml_event_delete (&event); } return TRUE; } static gboolean modulemd_packager_v3_parse_rpm_components (yaml_parser_t *parser, ModulemdPackagerV3 *packager, gboolean strict, GError **error) { MODULEMD_INIT_TRACE (); MMD_INIT_YAML_EVENT (event); gboolean done = FALSE; g_autoptr (GError) nested_error = NULL; g_autoptr (ModulemdComponentRpm) component = NULL; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); /* We *must* get a MAPPING_START here */ YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error); if (event.type != YAML_MAPPING_START_EVENT) { MMD_YAML_ERROR_EVENT_EXIT_BOOL ( error, event, "Got %s instead of MAPPING_START in rpm components.", mmd_yaml_get_event_name (event.type)); } while (!done) { YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error); switch (event.type) { case YAML_MAPPING_END_EVENT: done = TRUE; break; case YAML_SCALAR_EVENT: component = modulemd_component_rpm_parse_yaml ( parser, (const gchar *)event.data.scalar.value, strict, &nested_error); if (!component) { g_propagate_error (error, g_steal_pointer (&nested_error)); return FALSE; } modulemd_packager_v3_add_component (packager, (ModulemdComponent *)component); g_clear_pointer (&component, g_object_unref); break; default: MMD_YAML_ERROR_EVENT_EXIT_BOOL ( error, event, "Unexpected YAML event in RPM component: %s", mmd_yaml_get_event_name (event.type)); break; } yaml_event_delete (&event); } return TRUE; } static gboolean modulemd_packager_v3_parse_module_components (yaml_parser_t *parser, ModulemdPackagerV3 *packager, gboolean strict, GError **error) { MODULEMD_INIT_TRACE (); MMD_INIT_YAML_EVENT (event); gboolean done = FALSE; g_autoptr (GError) nested_error = NULL; g_autoptr (ModulemdComponentModule) component = NULL; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); /* We *must* get a MAPPING_START here */ YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error); if (event.type != YAML_MAPPING_START_EVENT) { MMD_YAML_ERROR_EVENT_EXIT_BOOL ( error, event, "Got %s instead of MAPPING_START in module components.", mmd_yaml_get_event_name (event.type)); } while (!done) { YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error); switch (event.type) { case YAML_MAPPING_END_EVENT: done = TRUE; break; case YAML_SCALAR_EVENT: component = modulemd_component_module_parse_yaml ( parser, (const gchar *)event.data.scalar.value, strict, &nested_error); if (!component) { g_propagate_error (error, g_steal_pointer (&nested_error)); return FALSE; } modulemd_packager_v3_add_component (packager, (ModulemdComponent *)component); g_clear_pointer (&component, g_object_unref); break; default: MMD_YAML_ERROR_EVENT_EXIT_BOOL ( error, event, "Unexpected YAML event in module component: %s", mmd_yaml_get_event_name (event.type)); break; } yaml_event_delete (&event); } return TRUE; } gboolean modulemd_packager_v3_emit_yaml (ModulemdPackagerV3 *self, yaml_emitter_t *emitter, GError **error) { MODULEMD_INIT_TRACE (); g_autoptr (GError) nested_error = NULL; gsize i; g_autoptr (GPtrArray) keys = NULL; gboolean ret; /* Emit document headers */ if (!modulemd_yaml_emit_document_headers ( emitter, MODULEMD_YAML_DOC_PACKAGER, MD_PACKAGER_VERSION_THREE, error)) { return FALSE; } /* Start data: */ EMIT_MAPPING_START (emitter, error); if (modulemd_packager_v3_get_module_name (self) != NULL) { EMIT_KEY_VALUE ( emitter, error, "name", modulemd_packager_v3_get_module_name (self)); } if (modulemd_packager_v3_get_stream_name (self) != NULL) { EMIT_KEY_VALUE_FULL (emitter, error, "stream", modulemd_packager_v3_get_stream_name (self), YAML_DOUBLE_QUOTED_SCALAR_STYLE); } EMIT_KEY_VALUE ( emitter, error, "summary", modulemd_packager_v3_get_summary (self)); EMIT_KEY_VALUE_FULL (emitter, error, "description", modulemd_packager_v3_get_description (self), YAML_FOLDED_SCALAR_STYLE); if (NON_EMPTY_TABLE (self->module_licenses)) { EMIT_STRING_SET (emitter, error, "license", self->module_licenses); } if (self->xmd != NULL) { EMIT_SCALAR (emitter, error, "xmd"); if (!modulemd_yaml_emit_variant (emitter, self->xmd, error)) { return FALSE; } } if (NON_EMPTY_TABLE (self->build_configs)) { EMIT_SCALAR (emitter, error, "configurations"); EMIT_SEQUENCE_START (emitter, error); keys = modulemd_ordered_str_keys (self->build_configs, modulemd_strcmp_sort); for (i = 0; i < keys->len; i++) { ret = modulemd_build_config_emit_yaml ( g_hash_table_lookup (self->build_configs, g_ptr_array_index (keys, i)), emitter, error); if (!ret) { return FALSE; } } EMIT_SEQUENCE_END (emitter, error); } if (self->community || self->documentation || self->tracker) { EMIT_SCALAR (emitter, error, "references"); EMIT_MAPPING_START (emitter, error); EMIT_KEY_VALUE_IF_SET (emitter, error, "community", self->community); EMIT_KEY_VALUE_IF_SET ( emitter, error, "documentation", self->documentation); EMIT_KEY_VALUE_IF_SET (emitter, error, "tracker", self->tracker); EMIT_MAPPING_END (emitter, error); } EMIT_HASHTABLE_VALUES_IF_NON_EMPTY ( emitter, error, "profiles", self->profiles, modulemd_profile_emit_yaml); if (NON_EMPTY_TABLE (self->rpm_api)) { EMIT_SCALAR (emitter, error, "api"); EMIT_MAPPING_START (emitter, error); EMIT_STRING_SET (emitter, error, "rpms", self->rpm_api); EMIT_MAPPING_END (emitter, error); } if (NON_EMPTY_TABLE (self->rpm_filters)) { EMIT_SCALAR (emitter, error, "filter"); EMIT_MAPPING_START (emitter, error); EMIT_STRING_SET (emitter, error, "rpms", self->rpm_filters); EMIT_MAPPING_END (emitter, error); } if (NON_EMPTY_TABLE (self->demodularized_rpms)) { EMIT_SCALAR (emitter, error, "demodularized"); EMIT_MAPPING_START (emitter, error); EMIT_STRING_SET (emitter, error, "rpms", self->demodularized_rpms); EMIT_MAPPING_END (emitter, error); } if (NON_EMPTY_TABLE (self->rpm_components) || NON_EMPTY_TABLE (self->module_components)) { EMIT_SCALAR (emitter, error, "components"); EMIT_MAPPING_START (emitter, error); EMIT_HASHTABLE_VALUES_IF_NON_EMPTY (emitter, error, "rpms", self->rpm_components, modulemd_component_rpm_emit_yaml); EMIT_HASHTABLE_VALUES_IF_NON_EMPTY (emitter, error, "modules", self->module_components, modulemd_component_module_emit_yaml); EMIT_MAPPING_END (emitter, error); } /* The "data" mapping */ EMIT_MAPPING_END (emitter, error); /* The overall document mapping */ EMIT_MAPPING_END (emitter, error); if (!mmd_emitter_end_document (emitter, error)) { return FALSE; } return TRUE; }