1 /*
2  * This file is part of libmodulemd
3  * Copyright (C) 2018 Red Hat, Inc.
4  *
5  * Fedora-License-Identifier: MIT
6  * SPDX-2.0-License-Identifier: MIT
7  * SPDX-3.0-License-Identifier: MIT
8  *
9  * This program is free software.
10  * For more information on the license, see COPYING.
11  * For more information on free software, see <https://www.gnu.org/philosophy/free-sw.en.html>.
12  */
13 
14 #include "modulemd-buildopts.h"
15 #include "modulemd-component-module.h"
16 #include "modulemd-component-rpm.h"
17 #include "modulemd-component.h"
18 #include "modulemd-errors.h"
19 #include "modulemd-module-stream-v1.h"
20 #include "modulemd-module-stream.h"
21 #include "modulemd-profile.h"
22 #include "modulemd-service-level.h"
23 #include "modulemd-translation-entry.h"
24 #include "private/glib-extensions.h"
25 #include "private/modulemd-buildopts-private.h"
26 #include "private/modulemd-component-module-private.h"
27 #include "private/modulemd-component-private.h"
28 #include "private/modulemd-component-rpm-private.h"
29 #include "private/modulemd-module-stream-private.h"
30 #include "private/modulemd-module-stream-v1-private.h"
31 #include "private/modulemd-profile-private.h"
32 #include "private/modulemd-service-level-private.h"
33 #include "private/modulemd-subdocument-info-private.h"
34 #include "private/modulemd-util.h"
35 #include "private/modulemd-yaml.h"
36 
37 
38 G_DEFINE_TYPE (ModulemdModuleStreamV1,
39                modulemd_module_stream_v1,
40                MODULEMD_TYPE_MODULE_STREAM)
41 
42 enum
43 {
44   PROP_0,
45   PROP_ARCH,
46   PROP_BUILDOPTS,
47   PROP_COMMUNITY,
48   PROP_DOCUMENTATION,
49   PROP_TRACKER,
50   N_PROPS
51 };
52 
53 static GParamSpec *properties[N_PROPS];
54 
55 ModulemdModuleStreamV1 *
modulemd_module_stream_v1_new(const gchar * module_name,const gchar * module_stream)56 modulemd_module_stream_v1_new (const gchar *module_name,
57                                const gchar *module_stream)
58 {
59   // clang-format off
60   return g_object_new (MODULEMD_TYPE_MODULE_STREAM_V1,
61                        "module-name", module_name,
62                        "stream-name", module_stream,
63                        NULL);
64   // clang-format on
65 }
66 
67 
68 static void
modulemd_module_stream_v1_finalize(GObject * object)69 modulemd_module_stream_v1_finalize (GObject *object)
70 {
71   ModulemdModuleStreamV1 *self = MODULEMD_MODULE_STREAM_V1 (object);
72 
73   /* Properties */
74   g_clear_object (&self->buildopts);
75   g_clear_pointer (&self->community, g_free);
76   g_clear_pointer (&self->description, g_free);
77   g_clear_pointer (&self->documentation, g_free);
78   g_clear_pointer (&self->summary, g_free);
79   g_clear_pointer (&self->tracker, g_free);
80 
81   /* Internal Data Structures */
82   g_clear_pointer (&self->module_components, g_hash_table_unref);
83   g_clear_pointer (&self->rpm_components, g_hash_table_unref);
84 
85   g_clear_pointer (&self->content_licenses, g_hash_table_unref);
86   g_clear_pointer (&self->module_licenses, g_hash_table_unref);
87 
88   g_clear_pointer (&self->profiles, g_hash_table_unref);
89 
90   g_clear_pointer (&self->rpm_api, g_hash_table_unref);
91 
92   g_clear_pointer (&self->rpm_artifacts, g_hash_table_unref);
93 
94   g_clear_pointer (&self->rpm_filters, g_hash_table_unref);
95 
96   g_clear_pointer (&self->servicelevels, g_hash_table_unref);
97 
98   g_clear_pointer (&self->buildtime_deps, g_hash_table_unref);
99   g_clear_pointer (&self->runtime_deps, g_hash_table_unref);
100 
101   g_clear_pointer (&self->xmd, g_variant_unref);
102 
103   G_OBJECT_CLASS (modulemd_module_stream_v1_parent_class)->finalize (object);
104 }
105 
106 
107 /* ===== Properties ====== */
108 
109 
110 static guint64
modulemd_module_stream_v1_get_mdversion(ModulemdModuleStream * self)111 modulemd_module_stream_v1_get_mdversion (ModulemdModuleStream *self)
112 {
113   return MD_MODULESTREAM_VERSION_ONE;
114 }
115 
116 void
modulemd_module_stream_v1_set_arch(ModulemdModuleStreamV1 * self,const gchar * arch)117 modulemd_module_stream_v1_set_arch (ModulemdModuleStreamV1 *self,
118                                     const gchar *arch)
119 {
120   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
121 
122   modulemd_module_stream_set_arch (MODULEMD_MODULE_STREAM (self), arch);
123 
124   g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ARCH]);
125 }
126 
127 
128 const gchar *
modulemd_module_stream_v1_get_arch(ModulemdModuleStreamV1 * self)129 modulemd_module_stream_v1_get_arch (ModulemdModuleStreamV1 *self)
130 {
131   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
132 
133   return modulemd_module_stream_get_arch (MODULEMD_MODULE_STREAM (self));
134 }
135 
136 
137 void
modulemd_module_stream_v1_set_buildopts(ModulemdModuleStreamV1 * self,ModulemdBuildopts * buildopts)138 modulemd_module_stream_v1_set_buildopts (ModulemdModuleStreamV1 *self,
139                                          ModulemdBuildopts *buildopts)
140 {
141   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
142 
143   g_clear_object (&self->buildopts);
144   self->buildopts = modulemd_buildopts_copy (buildopts);
145 
146   g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BUILDOPTS]);
147 }
148 
149 
150 ModulemdBuildopts *
modulemd_module_stream_v1_get_buildopts(ModulemdModuleStreamV1 * self)151 modulemd_module_stream_v1_get_buildopts (ModulemdModuleStreamV1 *self)
152 {
153   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
154 
155   return self->buildopts;
156 }
157 
158 
159 void
modulemd_module_stream_v1_set_community(ModulemdModuleStreamV1 * self,const gchar * community)160 modulemd_module_stream_v1_set_community (ModulemdModuleStreamV1 *self,
161                                          const gchar *community)
162 {
163   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
164 
165   g_clear_pointer (&self->community, g_free);
166   self->community = g_strdup (community);
167 
168   g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COMMUNITY]);
169 }
170 
171 
172 const gchar *
modulemd_module_stream_v1_get_community(ModulemdModuleStreamV1 * self)173 modulemd_module_stream_v1_get_community (ModulemdModuleStreamV1 *self)
174 {
175   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
176 
177   return self->community;
178 }
179 
180 
181 void
modulemd_module_stream_v1_set_description(ModulemdModuleStreamV1 * self,const gchar * description)182 modulemd_module_stream_v1_set_description (ModulemdModuleStreamV1 *self,
183                                            const gchar *description)
184 {
185   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
186 
187   g_clear_pointer (&self->description, g_free);
188   self->description = g_strdup (description);
189 }
190 
191 
192 const gchar *
modulemd_module_stream_v1_get_description(ModulemdModuleStreamV1 * self,const gchar * locale)193 modulemd_module_stream_v1_get_description (ModulemdModuleStreamV1 *self,
194                                            const gchar *locale)
195 {
196   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
197 
198   ModulemdTranslationEntry *entry =
199     modulemd_module_stream_get_translation_entry (
200       MODULEMD_MODULE_STREAM (self), locale);
201   if (entry != NULL &&
202       modulemd_translation_entry_get_description (entry) != NULL)
203     {
204       return modulemd_translation_entry_get_description (entry);
205     }
206 
207   return self->description;
208 }
209 
210 
211 void
modulemd_module_stream_v1_set_documentation(ModulemdModuleStreamV1 * self,const gchar * documentation)212 modulemd_module_stream_v1_set_documentation (ModulemdModuleStreamV1 *self,
213                                              const gchar *documentation)
214 {
215   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
216 
217   g_clear_pointer (&self->documentation, g_free);
218   self->documentation = g_strdup (documentation);
219 
220   g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COMMUNITY]);
221 }
222 
223 
224 const gchar *
modulemd_module_stream_v1_get_documentation(ModulemdModuleStreamV1 * self)225 modulemd_module_stream_v1_get_documentation (ModulemdModuleStreamV1 *self)
226 {
227   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
228 
229   return self->documentation;
230 }
231 
232 
233 void
modulemd_module_stream_v1_set_summary(ModulemdModuleStreamV1 * self,const gchar * summary)234 modulemd_module_stream_v1_set_summary (ModulemdModuleStreamV1 *self,
235                                        const gchar *summary)
236 {
237   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
238 
239   g_clear_pointer (&self->summary, g_free);
240   self->summary = g_strdup (summary);
241 }
242 
243 
244 const gchar *
modulemd_module_stream_v1_get_summary(ModulemdModuleStreamV1 * self,const gchar * locale)245 modulemd_module_stream_v1_get_summary (ModulemdModuleStreamV1 *self,
246                                        const gchar *locale)
247 {
248   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
249 
250   ModulemdTranslationEntry *entry =
251     modulemd_module_stream_get_translation_entry (
252       MODULEMD_MODULE_STREAM (self), locale);
253   if (entry != NULL && modulemd_translation_entry_get_summary (entry) != NULL)
254     {
255       return modulemd_translation_entry_get_summary (entry);
256     }
257 
258   return self->summary;
259 }
260 
261 
262 void
modulemd_module_stream_v1_set_tracker(ModulemdModuleStreamV1 * self,const gchar * tracker)263 modulemd_module_stream_v1_set_tracker (ModulemdModuleStreamV1 *self,
264                                        const gchar *tracker)
265 {
266   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
267 
268   g_clear_pointer (&self->tracker, g_free);
269   self->tracker = g_strdup (tracker);
270 
271   g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TRACKER]);
272 }
273 
274 
275 const gchar *
modulemd_module_stream_v1_get_tracker(ModulemdModuleStreamV1 * self)276 modulemd_module_stream_v1_get_tracker (ModulemdModuleStreamV1 *self)
277 {
278   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
279 
280   return self->tracker;
281 }
282 
283 
284 /* ===== Non-property Methods ===== */
285 
286 
287 void
modulemd_module_stream_v1_add_component(ModulemdModuleStreamV1 * self,ModulemdComponent * component)288 modulemd_module_stream_v1_add_component (ModulemdModuleStreamV1 *self,
289                                          ModulemdComponent *component)
290 {
291   GHashTable *table = NULL;
292 
293   /* Do nothing if we were passed a NULL component */
294   if (!component)
295     {
296       return;
297     }
298 
299   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
300   g_return_if_fail (MODULEMD_IS_COMPONENT (component));
301 
302   if (MODULEMD_IS_COMPONENT_RPM (component))
303     {
304       table = self->rpm_components;
305     }
306   else if (MODULEMD_IS_COMPONENT_MODULE (component))
307     {
308       table = self->module_components;
309     }
310   else
311     {
312       /* Unknown component. Raise a warning and return */
313       g_return_if_reached ();
314     }
315 
316   /* Add the component to the table. This will replace an existing component
317    * with the same name
318    */
319   g_hash_table_replace (table,
320                         g_strdup (modulemd_component_get_key (component)),
321                         modulemd_component_copy (component, NULL));
322 }
323 
324 
325 void
modulemd_module_stream_v1_remove_module_component(ModulemdModuleStreamV1 * self,const gchar * component_name)326 modulemd_module_stream_v1_remove_module_component (
327   ModulemdModuleStreamV1 *self, const gchar *component_name)
328 {
329   /* Do nothing if we were passed a NULL component_name */
330   if (!component_name)
331     {
332       return;
333     }
334 
335   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
336 
337   g_hash_table_remove (self->module_components, component_name);
338 }
339 
340 
341 void
modulemd_module_stream_v1_clear_module_components(ModulemdModuleStreamV1 * self)342 modulemd_module_stream_v1_clear_module_components (
343   ModulemdModuleStreamV1 *self)
344 {
345   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
346 
347   g_hash_table_remove_all (self->module_components);
348 }
349 
350 
351 void
modulemd_module_stream_v1_remove_rpm_component(ModulemdModuleStreamV1 * self,const gchar * component_name)352 modulemd_module_stream_v1_remove_rpm_component (ModulemdModuleStreamV1 *self,
353                                                 const gchar *component_name)
354 {
355   /* Do nothing if we were passed a NULL component_name */
356   if (!component_name)
357     {
358       return;
359     }
360 
361   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
362 
363   g_hash_table_remove (self->rpm_components, component_name);
364 }
365 
366 
367 void
modulemd_module_stream_v1_clear_rpm_components(ModulemdModuleStreamV1 * self)368 modulemd_module_stream_v1_clear_rpm_components (ModulemdModuleStreamV1 *self)
369 {
370   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
371 
372   g_hash_table_remove_all (self->rpm_components);
373 }
374 
375 
376 GStrv
modulemd_module_stream_v1_get_module_component_names_as_strv(ModulemdModuleStreamV1 * self)377 modulemd_module_stream_v1_get_module_component_names_as_strv (
378   ModulemdModuleStreamV1 *self)
379 {
380   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
381 
382   return modulemd_ordered_str_keys_as_strv (self->module_components);
383 }
384 
385 
386 GStrv
modulemd_module_stream_v1_get_rpm_component_names_as_strv(ModulemdModuleStreamV1 * self)387 modulemd_module_stream_v1_get_rpm_component_names_as_strv (
388   ModulemdModuleStreamV1 *self)
389 {
390   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
391 
392   return modulemd_ordered_str_keys_as_strv (self->rpm_components);
393 }
394 
395 
396 ModulemdComponentModule *
modulemd_module_stream_v1_get_module_component(ModulemdModuleStreamV1 * self,const gchar * component_name)397 modulemd_module_stream_v1_get_module_component (ModulemdModuleStreamV1 *self,
398                                                 const gchar *component_name)
399 {
400   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
401 
402   return g_hash_table_lookup (self->module_components, component_name);
403 }
404 
405 
406 ModulemdComponentRpm *
modulemd_module_stream_v1_get_rpm_component(ModulemdModuleStreamV1 * self,const gchar * component_name)407 modulemd_module_stream_v1_get_rpm_component (ModulemdModuleStreamV1 *self,
408                                              const gchar *component_name)
409 {
410   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
411 
412   return g_hash_table_lookup (self->rpm_components, component_name);
413 }
414 
415 
416 void
modulemd_module_stream_v1_add_content_license(ModulemdModuleStreamV1 * self,const gchar * license)417 modulemd_module_stream_v1_add_content_license (ModulemdModuleStreamV1 *self,
418                                                const gchar *license)
419 {
420   if (!license)
421     {
422       return;
423     }
424 
425   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
426 
427   g_hash_table_add (self->content_licenses, g_strdup (license));
428 }
429 
430 
431 static void
modulemd_module_stream_v1_replace_content_licenses(ModulemdModuleStreamV1 * self,GHashTable * set)432 modulemd_module_stream_v1_replace_content_licenses (
433   ModulemdModuleStreamV1 *self, GHashTable *set)
434 {
435   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
436 
437   MODULEMD_REPLACE_SET (self->content_licenses, set);
438 }
439 
440 
441 void
modulemd_module_stream_v1_clear_content_licenses(ModulemdModuleStreamV1 * self)442 modulemd_module_stream_v1_clear_content_licenses (ModulemdModuleStreamV1 *self)
443 {
444   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
445 
446   g_hash_table_remove_all (self->content_licenses);
447 }
448 
449 
450 void
modulemd_module_stream_v1_add_module_license(ModulemdModuleStreamV1 * self,const gchar * license)451 modulemd_module_stream_v1_add_module_license (ModulemdModuleStreamV1 *self,
452                                               const gchar *license)
453 {
454   if (!license)
455     {
456       return;
457     }
458 
459   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
460 
461   g_hash_table_add (self->module_licenses, g_strdup (license));
462 }
463 
464 
465 static void
modulemd_module_stream_v1_replace_module_licenses(ModulemdModuleStreamV1 * self,GHashTable * set)466 modulemd_module_stream_v1_replace_module_licenses (
467   ModulemdModuleStreamV1 *self, GHashTable *set)
468 {
469   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
470 
471   MODULEMD_REPLACE_SET (self->module_licenses, set);
472 }
473 
474 
475 void
modulemd_module_stream_v1_clear_module_licenses(ModulemdModuleStreamV1 * self)476 modulemd_module_stream_v1_clear_module_licenses (ModulemdModuleStreamV1 *self)
477 {
478   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
479 
480   g_hash_table_remove_all (self->module_licenses);
481 }
482 
483 
484 void
modulemd_module_stream_v1_remove_content_license(ModulemdModuleStreamV1 * self,const gchar * license)485 modulemd_module_stream_v1_remove_content_license (ModulemdModuleStreamV1 *self,
486                                                   const gchar *license)
487 {
488   if (!license)
489     {
490       return;
491     }
492 
493   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
494 
495   g_hash_table_remove (self->content_licenses, license);
496 }
497 
498 
499 void
modulemd_module_stream_v1_remove_module_license(ModulemdModuleStreamV1 * self,const gchar * license)500 modulemd_module_stream_v1_remove_module_license (ModulemdModuleStreamV1 *self,
501                                                  const gchar *license)
502 {
503   if (!license)
504     {
505       return;
506     }
507 
508   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
509 
510   g_hash_table_remove (self->module_licenses, license);
511 }
512 
513 
514 GStrv
modulemd_module_stream_v1_get_content_licenses_as_strv(ModulemdModuleStreamV1 * self)515 modulemd_module_stream_v1_get_content_licenses_as_strv (
516   ModulemdModuleStreamV1 *self)
517 {
518   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
519 
520   return modulemd_ordered_str_keys_as_strv (self->content_licenses);
521 }
522 
523 
524 GStrv
modulemd_module_stream_v1_get_module_licenses_as_strv(ModulemdModuleStreamV1 * self)525 modulemd_module_stream_v1_get_module_licenses_as_strv (
526   ModulemdModuleStreamV1 *self)
527 {
528   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
529 
530   return modulemd_ordered_str_keys_as_strv (self->module_licenses);
531 }
532 
533 
534 void
modulemd_module_stream_v1_add_profile(ModulemdModuleStreamV1 * self,ModulemdProfile * profile)535 modulemd_module_stream_v1_add_profile (ModulemdModuleStreamV1 *self,
536                                        ModulemdProfile *profile)
537 {
538   if (!profile)
539     {
540       return;
541     }
542   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
543   g_return_if_fail (MODULEMD_IS_PROFILE (profile));
544 
545   ModulemdProfile *copied_profile = modulemd_profile_copy (profile);
546   modulemd_profile_set_owner (copied_profile, MODULEMD_MODULE_STREAM (self));
547 
548   g_hash_table_replace (self->profiles,
549                         g_strdup (modulemd_profile_get_name (profile)),
550                         copied_profile);
551 }
552 
553 
554 void
modulemd_module_stream_v1_clear_profiles(ModulemdModuleStreamV1 * self)555 modulemd_module_stream_v1_clear_profiles (ModulemdModuleStreamV1 *self)
556 {
557   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
558 
559   g_hash_table_remove_all (self->profiles);
560 }
561 
562 
563 GStrv
modulemd_module_stream_v1_get_profile_names_as_strv(ModulemdModuleStreamV1 * self)564 modulemd_module_stream_v1_get_profile_names_as_strv (
565   ModulemdModuleStreamV1 *self)
566 {
567   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
568 
569   return modulemd_ordered_str_keys_as_strv (self->profiles);
570 }
571 
572 
573 ModulemdProfile *
modulemd_module_stream_v1_get_profile(ModulemdModuleStreamV1 * self,const gchar * profile_name)574 modulemd_module_stream_v1_get_profile (ModulemdModuleStreamV1 *self,
575                                        const gchar *profile_name)
576 {
577   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
578 
579   return g_hash_table_lookup (self->profiles, profile_name);
580 }
581 
582 
583 void
modulemd_module_stream_v1_add_rpm_api(ModulemdModuleStreamV1 * self,const gchar * rpm)584 modulemd_module_stream_v1_add_rpm_api (ModulemdModuleStreamV1 *self,
585                                        const gchar *rpm)
586 {
587   if (!rpm)
588     {
589       return;
590     }
591 
592   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
593 
594   g_hash_table_add (self->rpm_api, g_strdup (rpm));
595 }
596 
597 
598 static void
modulemd_module_stream_v1_replace_rpm_api(ModulemdModuleStreamV1 * self,GHashTable * set)599 modulemd_module_stream_v1_replace_rpm_api (ModulemdModuleStreamV1 *self,
600                                            GHashTable *set)
601 {
602   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
603 
604   MODULEMD_REPLACE_SET (self->rpm_api, set);
605 }
606 
607 
608 void
modulemd_module_stream_v1_remove_rpm_api(ModulemdModuleStreamV1 * self,const gchar * rpm)609 modulemd_module_stream_v1_remove_rpm_api (ModulemdModuleStreamV1 *self,
610                                           const gchar *rpm)
611 {
612   if (!rpm)
613     {
614       return;
615     }
616 
617   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
618 
619   g_hash_table_remove (self->rpm_api, rpm);
620 }
621 
622 
623 void
modulemd_module_stream_v1_clear_rpm_api(ModulemdModuleStreamV1 * self)624 modulemd_module_stream_v1_clear_rpm_api (ModulemdModuleStreamV1 *self)
625 {
626   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
627 
628   g_hash_table_remove_all (self->rpm_api);
629 }
630 
631 
632 GStrv
modulemd_module_stream_v1_get_rpm_api_as_strv(ModulemdModuleStreamV1 * self)633 modulemd_module_stream_v1_get_rpm_api_as_strv (ModulemdModuleStreamV1 *self)
634 {
635   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
636 
637   return modulemd_ordered_str_keys_as_strv (self->rpm_api);
638 }
639 
640 
641 void
modulemd_module_stream_v1_add_rpm_artifact(ModulemdModuleStreamV1 * self,const gchar * nevr)642 modulemd_module_stream_v1_add_rpm_artifact (ModulemdModuleStreamV1 *self,
643                                             const gchar *nevr)
644 {
645   if (!nevr)
646     {
647       return;
648     }
649 
650   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
651 
652   g_hash_table_add (self->rpm_artifacts, g_strdup (nevr));
653 }
654 
655 
656 static void
modulemd_module_stream_v1_replace_rpm_artifacts(ModulemdModuleStreamV1 * self,GHashTable * set)657 modulemd_module_stream_v1_replace_rpm_artifacts (ModulemdModuleStreamV1 *self,
658                                                  GHashTable *set)
659 {
660   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
661 
662   MODULEMD_REPLACE_SET (self->rpm_artifacts, set);
663 }
664 
665 
666 void
modulemd_module_stream_v1_remove_rpm_artifact(ModulemdModuleStreamV1 * self,const gchar * nevr)667 modulemd_module_stream_v1_remove_rpm_artifact (ModulemdModuleStreamV1 *self,
668                                                const gchar *nevr)
669 {
670   if (!nevr)
671     {
672       return;
673     }
674 
675   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
676 
677   g_hash_table_remove (self->rpm_artifacts, nevr);
678 }
679 
680 
681 void
modulemd_module_stream_v1_clear_rpm_artifacts(ModulemdModuleStreamV1 * self)682 modulemd_module_stream_v1_clear_rpm_artifacts (ModulemdModuleStreamV1 *self)
683 {
684   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
685 
686   g_hash_table_remove_all (self->rpm_artifacts);
687 }
688 
689 
690 GStrv
modulemd_module_stream_v1_get_rpm_artifacts_as_strv(ModulemdModuleStreamV1 * self)691 modulemd_module_stream_v1_get_rpm_artifacts_as_strv (
692   ModulemdModuleStreamV1 *self)
693 {
694   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
695 
696   return modulemd_ordered_str_keys_as_strv (self->rpm_artifacts);
697 }
698 
699 
700 void
modulemd_module_stream_v1_add_rpm_filter(ModulemdModuleStreamV1 * self,const gchar * rpm)701 modulemd_module_stream_v1_add_rpm_filter (ModulemdModuleStreamV1 *self,
702                                           const gchar *rpm)
703 {
704   if (!rpm)
705     {
706       return;
707     }
708 
709   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
710 
711   g_hash_table_add (self->rpm_filters, g_strdup (rpm));
712 }
713 
714 
715 static void
modulemd_module_stream_v1_replace_rpm_filters(ModulemdModuleStreamV1 * self,GHashTable * set)716 modulemd_module_stream_v1_replace_rpm_filters (ModulemdModuleStreamV1 *self,
717                                                GHashTable *set)
718 {
719   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
720 
721   MODULEMD_REPLACE_SET (self->rpm_filters, set);
722 }
723 
724 
725 void
modulemd_module_stream_v1_remove_rpm_filter(ModulemdModuleStreamV1 * self,const gchar * rpm)726 modulemd_module_stream_v1_remove_rpm_filter (ModulemdModuleStreamV1 *self,
727                                              const gchar *rpm)
728 {
729   if (!rpm)
730     {
731       return;
732     }
733 
734   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
735 
736   g_hash_table_remove (self->rpm_filters, rpm);
737 }
738 
739 
740 void
modulemd_module_stream_v1_clear_rpm_filters(ModulemdModuleStreamV1 * self)741 modulemd_module_stream_v1_clear_rpm_filters (ModulemdModuleStreamV1 *self)
742 {
743   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
744 
745   g_hash_table_remove_all (self->rpm_filters);
746 }
747 
748 
749 GStrv
modulemd_module_stream_v1_get_rpm_filters_as_strv(ModulemdModuleStreamV1 * self)750 modulemd_module_stream_v1_get_rpm_filters_as_strv (
751   ModulemdModuleStreamV1 *self)
752 {
753   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
754 
755   return modulemd_ordered_str_keys_as_strv (self->rpm_filters);
756 }
757 
758 
759 void
modulemd_module_stream_v1_add_servicelevel(ModulemdModuleStreamV1 * self,ModulemdServiceLevel * servicelevel)760 modulemd_module_stream_v1_add_servicelevel (ModulemdModuleStreamV1 *self,
761                                             ModulemdServiceLevel *servicelevel)
762 {
763   if (!servicelevel)
764     {
765       return;
766     }
767   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
768   g_return_if_fail (MODULEMD_IS_SERVICE_LEVEL (servicelevel));
769 
770   g_hash_table_replace (
771     self->servicelevels,
772     g_strdup (modulemd_service_level_get_name (servicelevel)),
773     modulemd_service_level_copy (servicelevel));
774 }
775 
776 
777 void
modulemd_module_stream_v1_clear_servicelevels(ModulemdModuleStreamV1 * self)778 modulemd_module_stream_v1_clear_servicelevels (ModulemdModuleStreamV1 *self)
779 {
780   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
781 
782   g_hash_table_remove_all (self->servicelevels);
783 }
784 
785 
786 GStrv
modulemd_module_stream_v1_get_servicelevel_names_as_strv(ModulemdModuleStreamV1 * self)787 modulemd_module_stream_v1_get_servicelevel_names_as_strv (
788   ModulemdModuleStreamV1 *self)
789 {
790   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
791 
792   return modulemd_ordered_str_keys_as_strv (self->servicelevels);
793 }
794 
795 
796 ModulemdServiceLevel *
modulemd_module_stream_v1_get_servicelevel(ModulemdModuleStreamV1 * self,const gchar * servicelevel_name)797 modulemd_module_stream_v1_get_servicelevel (ModulemdModuleStreamV1 *self,
798                                             const gchar *servicelevel_name)
799 {
800   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
801 
802   return g_hash_table_lookup (self->servicelevels, servicelevel_name);
803 }
804 
805 
806 void
modulemd_module_stream_v1_set_eol(ModulemdModuleStreamV1 * self,GDate * eol)807 modulemd_module_stream_v1_set_eol (ModulemdModuleStreamV1 *self, GDate *eol)
808 {
809   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
810 
811   /* The "eol" field in the YAML is a relic of an early iteration and has been
812    * entirely replaced by the ServiceLevel concept. If we encounter it, we just
813    * treat it as if it was the EOL value for a service level named "rawhide".
814    */
815   g_autoptr (ModulemdServiceLevel) sl = modulemd_service_level_new ("rawhide");
816   modulemd_service_level_set_eol (sl, eol);
817 
818   return modulemd_module_stream_v1_add_servicelevel (self, sl);
819 }
820 
821 
822 GDate *
modulemd_module_stream_v1_get_eol(ModulemdModuleStreamV1 * self)823 modulemd_module_stream_v1_get_eol (ModulemdModuleStreamV1 *self)
824 {
825   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
826 
827   ModulemdServiceLevel *sl =
828     modulemd_module_stream_v1_get_servicelevel (self, "rawhide");
829 
830   return modulemd_service_level_get_eol (sl);
831 }
832 
833 
834 void
modulemd_module_stream_v1_add_buildtime_requirement(ModulemdModuleStreamV1 * self,const gchar * module_name,const gchar * module_stream)835 modulemd_module_stream_v1_add_buildtime_requirement (
836   ModulemdModuleStreamV1 *self,
837   const gchar *module_name,
838   const gchar *module_stream)
839 {
840   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
841   g_return_if_fail (module_name && module_stream);
842 
843   g_hash_table_replace (
844     self->buildtime_deps, g_strdup (module_name), g_strdup (module_stream));
845 }
846 
847 
848 static void
modulemd_module_stream_v1_replace_buildtime_deps(ModulemdModuleStreamV1 * self,GHashTable * deps)849 modulemd_module_stream_v1_replace_buildtime_deps (ModulemdModuleStreamV1 *self,
850                                                   GHashTable *deps)
851 {
852   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
853 
854   if (deps)
855     {
856       g_hash_table_unref (self->buildtime_deps);
857       self->buildtime_deps = modulemd_hash_table_deep_str_copy (deps);
858     }
859   else
860     {
861       g_hash_table_remove_all (self->buildtime_deps);
862     }
863 }
864 
865 
866 void
modulemd_module_stream_v1_add_runtime_requirement(ModulemdModuleStreamV1 * self,const gchar * module_name,const gchar * module_stream)867 modulemd_module_stream_v1_add_runtime_requirement (
868   ModulemdModuleStreamV1 *self,
869   const gchar *module_name,
870   const gchar *module_stream)
871 {
872   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
873   g_return_if_fail (module_name && module_stream);
874 
875   g_hash_table_replace (
876     self->runtime_deps, g_strdup (module_name), g_strdup (module_stream));
877 }
878 
879 
880 static void
modulemd_module_stream_v1_replace_runtime_deps(ModulemdModuleStreamV1 * self,GHashTable * deps)881 modulemd_module_stream_v1_replace_runtime_deps (ModulemdModuleStreamV1 *self,
882                                                 GHashTable *deps)
883 {
884   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
885 
886   if (deps)
887     {
888       g_hash_table_unref (self->runtime_deps);
889       self->runtime_deps = modulemd_hash_table_deep_str_copy (deps);
890     }
891   else
892     {
893       g_hash_table_remove_all (self->runtime_deps);
894     }
895 }
896 
897 
898 void
modulemd_module_stream_v1_remove_buildtime_requirement(ModulemdModuleStreamV1 * self,const gchar * module_name)899 modulemd_module_stream_v1_remove_buildtime_requirement (
900   ModulemdModuleStreamV1 *self, const gchar *module_name)
901 {
902   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
903   g_return_if_fail (module_name);
904 
905   g_hash_table_remove (self->buildtime_deps, module_name);
906 }
907 
908 
909 void
modulemd_module_stream_v1_remove_runtime_requirement(ModulemdModuleStreamV1 * self,const gchar * module_name)910 modulemd_module_stream_v1_remove_runtime_requirement (
911   ModulemdModuleStreamV1 *self, const gchar *module_name)
912 {
913   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
914   g_return_if_fail (module_name);
915 
916   g_hash_table_remove (self->runtime_deps, module_name);
917 }
918 
919 
920 void
modulemd_module_stream_v1_clear_buildtime_requirements(ModulemdModuleStreamV1 * self)921 modulemd_module_stream_v1_clear_buildtime_requirements (
922   ModulemdModuleStreamV1 *self)
923 {
924   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
925 
926   g_hash_table_remove_all (self->buildtime_deps);
927 }
928 
929 
930 void
modulemd_module_stream_v1_clear_runtime_requirements(ModulemdModuleStreamV1 * self)931 modulemd_module_stream_v1_clear_runtime_requirements (
932   ModulemdModuleStreamV1 *self)
933 {
934   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
935 
936   g_hash_table_remove_all (self->runtime_deps);
937 }
938 
939 
940 GStrv
modulemd_module_stream_v1_get_buildtime_modules_as_strv(ModulemdModuleStreamV1 * self)941 modulemd_module_stream_v1_get_buildtime_modules_as_strv (
942   ModulemdModuleStreamV1 *self)
943 {
944   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
945 
946   return modulemd_ordered_str_keys_as_strv (self->buildtime_deps);
947 }
948 
949 
950 GStrv
modulemd_module_stream_v1_get_runtime_modules_as_strv(ModulemdModuleStreamV1 * self)951 modulemd_module_stream_v1_get_runtime_modules_as_strv (
952   ModulemdModuleStreamV1 *self)
953 {
954   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
955 
956   return modulemd_ordered_str_keys_as_strv (self->runtime_deps);
957 }
958 
959 
960 const gchar *
modulemd_module_stream_v1_get_buildtime_requirement_stream(ModulemdModuleStreamV1 * self,const gchar * module_name)961 modulemd_module_stream_v1_get_buildtime_requirement_stream (
962   ModulemdModuleStreamV1 *self, const gchar *module_name)
963 {
964   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
965 
966   return g_hash_table_lookup (self->buildtime_deps, module_name);
967 }
968 
969 
970 const gchar *
modulemd_module_stream_v1_get_runtime_requirement_stream(ModulemdModuleStreamV1 * self,const gchar * module_name)971 modulemd_module_stream_v1_get_runtime_requirement_stream (
972   ModulemdModuleStreamV1 *self, const gchar *module_name)
973 {
974   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
975 
976   return g_hash_table_lookup (self->runtime_deps, module_name);
977 }
978 
979 
980 void
modulemd_module_stream_v1_set_xmd(ModulemdModuleStreamV1 * self,GVariant * xmd)981 modulemd_module_stream_v1_set_xmd (ModulemdModuleStreamV1 *self, GVariant *xmd)
982 {
983   g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
984 
985   /* Do nothing if we were passed the same pointer */
986   if (self->xmd == xmd)
987     {
988       return;
989     }
990 
991   g_clear_pointer (&self->xmd, g_variant_unref);
992   self->xmd = modulemd_variant_deep_copy (xmd);
993 }
994 
995 GVariant *
modulemd_module_stream_v1_get_xmd(ModulemdModuleStreamV1 * self)996 modulemd_module_stream_v1_get_xmd (ModulemdModuleStreamV1 *self)
997 {
998   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
999 
1000   return self->xmd;
1001 }
1002 
1003 
1004 gboolean
modulemd_module_stream_v1_includes_nevra(ModulemdModuleStreamV1 * self,const gchar * nevra_pattern)1005 modulemd_module_stream_v1_includes_nevra (ModulemdModuleStreamV1 *self,
1006                                           const gchar *nevra_pattern)
1007 {
1008   /* If g_hash_table_find() returns non-NULL, the nevra was found in this
1009    * module stream, so return TRUE
1010    */
1011   return !!g_hash_table_find (
1012     self->rpm_artifacts, modulemd_rpm_match, (void *)nevra_pattern);
1013 }
1014 
1015 static gboolean
modulemd_module_stream_v1_equals(ModulemdModuleStream * self_1,ModulemdModuleStream * self_2)1016 modulemd_module_stream_v1_equals (ModulemdModuleStream *self_1,
1017                                   ModulemdModuleStream *self_2)
1018 {
1019   ModulemdModuleStreamV1 *v1_self_1 = NULL;
1020   ModulemdModuleStreamV1 *v1_self_2 = NULL;
1021 
1022   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self_1), FALSE);
1023   v1_self_1 = MODULEMD_MODULE_STREAM_V1 (self_1);
1024   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self_2), FALSE);
1025   v1_self_2 = MODULEMD_MODULE_STREAM_V1 (self_2);
1026 
1027   if (!MODULEMD_MODULE_STREAM_CLASS (modulemd_module_stream_v1_parent_class)
1028          ->equals (self_1, self_2))
1029     {
1030       return FALSE;
1031     }
1032 
1033   /*Check property equality*/
1034   if (g_strcmp0 (v1_self_1->community, v1_self_2->community) != 0)
1035     {
1036       return FALSE;
1037     }
1038 
1039   if (g_strcmp0 (v1_self_1->description, v1_self_2->description) != 0)
1040     {
1041       return FALSE;
1042     }
1043 
1044   if (g_strcmp0 (v1_self_1->documentation, v1_self_2->documentation) != 0)
1045     {
1046       return FALSE;
1047     }
1048 
1049   if (g_strcmp0 (v1_self_1->summary, v1_self_2->summary) != 0)
1050     {
1051       return FALSE;
1052     }
1053 
1054   if (g_strcmp0 (v1_self_1->tracker, v1_self_2->tracker) != 0)
1055     {
1056       return FALSE;
1057     }
1058 
1059   if (!modulemd_buildopts_equals (v1_self_1->buildopts, v1_self_2->buildopts))
1060     {
1061       return FALSE;
1062     }
1063 
1064   if (!modulemd_hash_table_equals (v1_self_1->rpm_components,
1065                                    v1_self_2->rpm_components,
1066                                    modulemd_component_equals_wrapper))
1067     {
1068       return FALSE;
1069     }
1070 
1071   if (!modulemd_hash_table_equals (v1_self_1->module_components,
1072                                    v1_self_2->module_components,
1073                                    modulemd_component_equals_wrapper))
1074     {
1075       return FALSE;
1076     }
1077 
1078   if (!modulemd_hash_table_sets_are_equal (v1_self_1->module_licenses,
1079                                            v1_self_2->module_licenses))
1080     {
1081       return FALSE;
1082     }
1083 
1084   if (!modulemd_hash_table_sets_are_equal (v1_self_1->content_licenses,
1085                                            v1_self_2->content_licenses))
1086     {
1087       return FALSE;
1088     }
1089 
1090   if (!modulemd_hash_table_equals (v1_self_1->profiles,
1091                                    v1_self_2->profiles,
1092                                    modulemd_profile_equals_wrapper))
1093     {
1094       return FALSE;
1095     }
1096 
1097   if (!modulemd_hash_table_sets_are_equal (v1_self_1->rpm_api,
1098                                            v1_self_2->rpm_api))
1099     {
1100       return FALSE;
1101     }
1102 
1103   if (!modulemd_hash_table_sets_are_equal (v1_self_1->rpm_artifacts,
1104                                            v1_self_2->rpm_artifacts))
1105     {
1106       return FALSE;
1107     }
1108 
1109   if (!modulemd_hash_table_sets_are_equal (v1_self_1->rpm_filters,
1110                                            v1_self_2->rpm_filters))
1111     {
1112       return FALSE;
1113     }
1114 
1115   if (!modulemd_hash_table_equals (v1_self_1->servicelevels,
1116                                    v1_self_2->servicelevels,
1117                                    modulemd_service_level_equals_wrapper))
1118     {
1119       return FALSE;
1120     }
1121 
1122   if (!modulemd_hash_table_equals (
1123         v1_self_1->buildtime_deps, v1_self_2->buildtime_deps, g_str_equal))
1124     {
1125       return FALSE;
1126     }
1127 
1128   if (!modulemd_hash_table_equals (
1129         v1_self_1->runtime_deps, v1_self_2->runtime_deps, g_str_equal))
1130     {
1131       return FALSE;
1132     }
1133 
1134   if (v1_self_1->xmd == NULL && v1_self_2->xmd == NULL)
1135     {
1136       return TRUE;
1137     }
1138 
1139   if (v1_self_1->xmd == NULL || v1_self_2->xmd == NULL)
1140     {
1141       return FALSE;
1142     }
1143 
1144   if (!g_variant_equal (v1_self_1->xmd, v1_self_2->xmd))
1145     {
1146       return FALSE;
1147     }
1148 
1149   return TRUE;
1150 }
1151 
1152 
1153 static gboolean
modulemd_module_stream_v1_validate(ModulemdModuleStream * self,GError ** error)1154 modulemd_module_stream_v1_validate (ModulemdModuleStream *self, GError **error)
1155 {
1156   GHashTableIter iter;
1157   gpointer key;
1158   gpointer value;
1159   gchar *nevra = NULL;
1160   ModulemdModuleStreamV1 *v1_self = NULL;
1161   g_autoptr (GError) nested_error = NULL;
1162 
1163   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), FALSE);
1164   v1_self = MODULEMD_MODULE_STREAM_V1 (self);
1165 
1166   if (!MODULEMD_MODULE_STREAM_CLASS (modulemd_module_stream_v1_parent_class)
1167          ->validate (self, error))
1168     {
1169       return FALSE;
1170     }
1171 
1172   /* Make sure that mandatory fields are present */
1173   if (!modulemd_module_stream_v1_get_summary (v1_self, "C"))
1174     {
1175       g_set_error (error,
1176                    MODULEMD_YAML_ERROR,
1177                    MMD_YAML_ERROR_MISSING_REQUIRED,
1178                    "Summary is missing");
1179       return FALSE;
1180     }
1181 
1182   if (!modulemd_module_stream_v1_get_description (v1_self, "C"))
1183     {
1184       g_set_error (error,
1185                    MODULEMD_YAML_ERROR,
1186                    MMD_YAML_ERROR_MISSING_REQUIRED,
1187                    "Description is missing");
1188       return FALSE;
1189     }
1190 
1191   if (!g_hash_table_size (v1_self->module_licenses))
1192     {
1193       g_set_error (error,
1194                    MODULEMD_YAML_ERROR,
1195                    MMD_YAML_ERROR_MISSING_REQUIRED,
1196                    "Module license is missing");
1197       return FALSE;
1198     }
1199 
1200   /* Verify that the components are consistent with regards to buildorder and
1201    * buildafter values.
1202    */
1203   if (!modulemd_module_stream_validate_components (v1_self->rpm_components,
1204                                                    &nested_error))
1205     {
1206       g_propagate_error (error, g_steal_pointer (&nested_error));
1207       return FALSE;
1208     }
1209 
1210   /* Iterate through the artifacts and validate that they are in the proper
1211    * NEVRA format
1212    */
1213   g_hash_table_iter_init (&iter, v1_self->rpm_artifacts);
1214   while (g_hash_table_iter_next (&iter, &key, &value))
1215     {
1216       nevra = (gchar *)key;
1217       if (!modulemd_validate_nevra (nevra))
1218         {
1219           g_set_error (error,
1220                        MODULEMD_ERROR,
1221                        MMD_ERROR_VALIDATE,
1222                        "Artifact '%s' was not in valid N-E:V-R.A format.",
1223                        nevra);
1224           return FALSE;
1225         }
1226     }
1227 
1228   return TRUE;
1229 }
1230 
1231 
1232 static void
modulemd_module_stream_v1_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1233 modulemd_module_stream_v1_get_property (GObject *object,
1234                                         guint prop_id,
1235                                         GValue *value,
1236                                         GParamSpec *pspec)
1237 {
1238   ModulemdModuleStreamV1 *self = MODULEMD_MODULE_STREAM_V1 (object);
1239 
1240   switch (prop_id)
1241     {
1242     case PROP_ARCH:
1243       g_value_set_string (value, modulemd_module_stream_v1_get_arch (self));
1244       break;
1245 
1246     case PROP_BUILDOPTS:
1247       g_value_set_object (value,
1248                           modulemd_module_stream_v1_get_buildopts (self));
1249       break;
1250 
1251     case PROP_COMMUNITY:
1252       g_value_set_string (value,
1253                           modulemd_module_stream_v1_get_community (self));
1254       break;
1255 
1256     case PROP_DOCUMENTATION:
1257       g_value_set_string (value,
1258                           modulemd_module_stream_v1_get_documentation (self));
1259       break;
1260 
1261     case PROP_TRACKER:
1262       g_value_set_string (value, modulemd_module_stream_v1_get_tracker (self));
1263       break;
1264 
1265     default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1266     }
1267 }
1268 
1269 static void
modulemd_module_stream_v1_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1270 modulemd_module_stream_v1_set_property (GObject *object,
1271                                         guint prop_id,
1272                                         const GValue *value,
1273                                         GParamSpec *pspec)
1274 {
1275   ModulemdModuleStreamV1 *self = MODULEMD_MODULE_STREAM_V1 (object);
1276 
1277   switch (prop_id)
1278     {
1279     case PROP_ARCH:
1280       modulemd_module_stream_v1_set_arch (self, g_value_get_string (value));
1281       break;
1282 
1283     case PROP_BUILDOPTS:
1284       modulemd_module_stream_v1_set_buildopts (self,
1285                                                g_value_get_object (value));
1286       break;
1287 
1288     case PROP_COMMUNITY:
1289       modulemd_module_stream_v1_set_community (self,
1290                                                g_value_get_string (value));
1291       break;
1292 
1293     case PROP_DOCUMENTATION:
1294       modulemd_module_stream_v1_set_documentation (self,
1295                                                    g_value_get_string (value));
1296       break;
1297 
1298     case PROP_TRACKER:
1299       modulemd_module_stream_v1_set_tracker (self, g_value_get_string (value));
1300       break;
1301 
1302     default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1303     }
1304 }
1305 
1306 
1307 static ModulemdModuleStream *
modulemd_module_stream_v1_copy(ModulemdModuleStream * self,const gchar * module_name,const gchar * module_stream)1308 modulemd_module_stream_v1_copy (ModulemdModuleStream *self,
1309                                 const gchar *module_name,
1310                                 const gchar *module_stream)
1311 {
1312   ModulemdModuleStreamV1 *v1_self = NULL;
1313   g_autoptr (ModulemdModuleStreamV1) copy = NULL;
1314   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), NULL);
1315   v1_self = MODULEMD_MODULE_STREAM_V1 (self);
1316 
1317   copy = MODULEMD_MODULE_STREAM_V1 (
1318     MODULEMD_MODULE_STREAM_CLASS (modulemd_module_stream_v1_parent_class)
1319       ->copy (self, module_name, module_stream));
1320 
1321   /* Properties */
1322   STREAM_COPY_IF_SET (v1, copy, v1_self, arch);
1323   STREAM_COPY_IF_SET (v1, copy, v1_self, buildopts);
1324   STREAM_COPY_IF_SET (v1, copy, v1_self, community);
1325   STREAM_COPY_IF_SET_WITH_LOCALE (v1, copy, v1_self, description);
1326   STREAM_COPY_IF_SET (v1, copy, v1_self, documentation);
1327   STREAM_COPY_IF_SET_WITH_LOCALE (v1, copy, v1_self, summary);
1328   STREAM_COPY_IF_SET (v1, copy, v1_self, tracker);
1329 
1330   /* Internal Data Structures: With replace function */
1331   STREAM_REPLACE_HASHTABLE (v1, copy, v1_self, content_licenses);
1332   STREAM_REPLACE_HASHTABLE (v1, copy, v1_self, module_licenses);
1333   STREAM_REPLACE_HASHTABLE (v1, copy, v1_self, rpm_api);
1334   STREAM_REPLACE_HASHTABLE (v1, copy, v1_self, rpm_artifacts);
1335   STREAM_REPLACE_HASHTABLE (v1, copy, v1_self, rpm_filters);
1336   STREAM_REPLACE_HASHTABLE (v1, copy, v1_self, buildtime_deps);
1337   STREAM_REPLACE_HASHTABLE (v1, copy, v1_self, runtime_deps);
1338 
1339   /* Internal Data Structures: With add on value */
1340   COPY_HASHTABLE_BY_VALUE_ADDER (
1341     copy, v1_self, rpm_components, modulemd_module_stream_v1_add_component);
1342   COPY_HASHTABLE_BY_VALUE_ADDER (
1343     copy, v1_self, module_components, modulemd_module_stream_v1_add_component);
1344   COPY_HASHTABLE_BY_VALUE_ADDER (
1345     copy, v1_self, profiles, modulemd_module_stream_v1_add_profile);
1346   COPY_HASHTABLE_BY_VALUE_ADDER (
1347     copy, v1_self, servicelevels, modulemd_module_stream_v1_add_servicelevel);
1348 
1349   STREAM_COPY_IF_SET (v1, copy, v1_self, xmd);
1350 
1351   return MODULEMD_MODULE_STREAM (g_steal_pointer (&copy));
1352 }
1353 
1354 
1355 static gboolean
modulemd_module_stream_v1_depends_on_stream(ModulemdModuleStream * self,const gchar * module_name,const gchar * stream_name)1356 modulemd_module_stream_v1_depends_on_stream (ModulemdModuleStream *self,
1357                                              const gchar *module_name,
1358                                              const gchar *stream_name)
1359 {
1360   const gchar *stream = NULL;
1361   ModulemdModuleStreamV1 *v1_self = NULL;
1362 
1363   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), FALSE);
1364   g_return_val_if_fail (module_name && stream_name, FALSE);
1365 
1366   v1_self = MODULEMD_MODULE_STREAM_V1 (self);
1367 
1368   stream = g_hash_table_lookup (v1_self->runtime_deps, module_name);
1369   if (!stream)
1370     {
1371       return FALSE;
1372     }
1373 
1374   return g_str_equal (stream, stream_name);
1375 }
1376 
1377 
1378 static gboolean
modulemd_module_stream_v1_build_depends_on_stream(ModulemdModuleStream * self,const gchar * module_name,const gchar * stream_name)1379 modulemd_module_stream_v1_build_depends_on_stream (ModulemdModuleStream *self,
1380                                                    const gchar *module_name,
1381                                                    const gchar *stream_name)
1382 {
1383   const gchar *stream = NULL;
1384   ModulemdModuleStreamV1 *v1_self = NULL;
1385 
1386   g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self), FALSE);
1387   g_return_val_if_fail (module_name && stream_name, FALSE);
1388 
1389   v1_self = MODULEMD_MODULE_STREAM_V1 (self);
1390 
1391   stream = g_hash_table_lookup (v1_self->buildtime_deps, module_name);
1392   if (!stream)
1393     {
1394       return FALSE;
1395     }
1396 
1397   return g_str_equal (stream, stream_name);
1398 }
1399 
1400 
1401 static void
modulemd_module_stream_v1_class_init(ModulemdModuleStreamV1Class * klass)1402 modulemd_module_stream_v1_class_init (ModulemdModuleStreamV1Class *klass)
1403 {
1404   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1405   ModulemdModuleStreamClass *stream_class =
1406     MODULEMD_MODULE_STREAM_CLASS (object_class);
1407 
1408   object_class->finalize = modulemd_module_stream_v1_finalize;
1409   object_class->get_property = modulemd_module_stream_v1_get_property;
1410   object_class->set_property = modulemd_module_stream_v1_set_property;
1411 
1412   stream_class->get_mdversion = modulemd_module_stream_v1_get_mdversion;
1413   stream_class->copy = modulemd_module_stream_v1_copy;
1414   stream_class->equals = modulemd_module_stream_v1_equals;
1415   stream_class->validate = modulemd_module_stream_v1_validate;
1416   stream_class->depends_on_stream =
1417     modulemd_module_stream_v1_depends_on_stream;
1418   stream_class->build_depends_on_stream =
1419     modulemd_module_stream_v1_build_depends_on_stream;
1420 
1421   properties[PROP_ARCH] = g_param_spec_string (
1422     "arch",
1423     "Module Artifact Architecture",
1424     "The architecture of the produced artifacts",
1425     NULL,
1426     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
1427 
1428   properties[PROP_BUILDOPTS] =
1429     g_param_spec_object ("buildopts",
1430                          "Module Build Options",
1431                          "Build options for module components",
1432                          MODULEMD_TYPE_BUILDOPTS,
1433                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1434 
1435   properties[PROP_COMMUNITY] = g_param_spec_string (
1436     "community",
1437     "Module Community Website",
1438     "The website address of the upstream community for this module",
1439     NULL,
1440     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
1441 
1442   properties[PROP_DOCUMENTATION] = g_param_spec_string (
1443     "documentation",
1444     "Module Documentation Website",
1445     "The website address of the upstream documentation for this module",
1446     NULL,
1447     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
1448 
1449   properties[PROP_TRACKER] = g_param_spec_string (
1450     "tracker",
1451     "Module Bug Tracker Website",
1452     "The website address of the upstream bug tracker for this module",
1453     NULL,
1454     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
1455 
1456   g_object_class_install_properties (object_class, N_PROPS, properties);
1457 }
1458 
1459 static void
modulemd_module_stream_v1_init(ModulemdModuleStreamV1 * self)1460 modulemd_module_stream_v1_init (ModulemdModuleStreamV1 *self)
1461 {
1462   /* Properties */
1463 
1464   /* Internal Data Structures */
1465   self->module_components =
1466     g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
1467   self->rpm_components =
1468     g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
1469 
1470   self->content_licenses =
1471     g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1472   self->module_licenses =
1473     g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1474 
1475   self->profiles =
1476     g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
1477 
1478   self->rpm_api =
1479     g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1480 
1481   self->rpm_artifacts =
1482     g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1483 
1484   self->rpm_filters =
1485     g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1486 
1487   self->servicelevels =
1488     g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
1489 
1490   self->buildtime_deps =
1491     g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1492   self->runtime_deps =
1493     g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1494 }
1495 
1496 
1497 static gboolean
1498 modulemd_module_stream_v1_parse_licenses (yaml_parser_t *parser,
1499                                           ModulemdModuleStreamV1 *modulestream,
1500                                           gboolean strict,
1501                                           GError **error);
1502 
1503 static gboolean
1504 modulemd_module_stream_v1_parse_servicelevels (
1505   yaml_parser_t *parser,
1506   ModulemdModuleStreamV1 *modulestream,
1507   gboolean strict,
1508   GError **error);
1509 
1510 static gboolean
1511 modulemd_module_stream_v1_parse_deps (yaml_parser_t *parser,
1512                                       ModulemdModuleStreamV1 *modulestream,
1513                                       gboolean strict,
1514                                       GError **error);
1515 
1516 static gboolean
1517 modulemd_module_stream_v1_parse_refs (yaml_parser_t *parser,
1518                                       ModulemdModuleStreamV1 *modulestream,
1519                                       gboolean strict,
1520                                       GError **error);
1521 
1522 static gboolean
1523 modulemd_module_stream_v1_parse_profiles (yaml_parser_t *parser,
1524                                           ModulemdModuleStreamV1 *modulestream,
1525                                           gboolean strict,
1526                                           GError **error);
1527 
1528 static gboolean
1529 modulemd_module_stream_v1_parse_components (
1530   yaml_parser_t *parser,
1531   ModulemdModuleStreamV1 *modulestream,
1532   gboolean strict,
1533   GError **error);
1534 
1535 
1536 ModulemdModuleStreamV1 *
modulemd_module_stream_v1_parse_yaml(ModulemdSubdocumentInfo * subdoc,gboolean strict,GError ** error)1537 modulemd_module_stream_v1_parse_yaml (ModulemdSubdocumentInfo *subdoc,
1538                                       gboolean strict,
1539                                       GError **error)
1540 {
1541   MODULEMD_INIT_TRACE ();
1542   MMD_INIT_YAML_PARSER (parser);
1543   MMD_INIT_YAML_EVENT (event);
1544   gboolean done = FALSE;
1545   g_autoptr (GError) nested_error = NULL;
1546   g_autoptr (ModulemdModuleStreamV1) modulestream = NULL;
1547   g_autoptr (GHashTable) set = NULL;
1548   g_autoptr (ModulemdBuildopts) buildopts = NULL;
1549   g_autoptr (GVariant) xmd = NULL;
1550   g_autoptr (GDate) eol = NULL;
1551   g_autoptr (ModulemdServiceLevel) sl = NULL;
1552 
1553   if (!modulemd_subdocument_info_get_data_parser (
1554         subdoc, &parser, strict, error))
1555     {
1556       return NULL;
1557     }
1558 
1559   guint64 version;
1560 
1561   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1562 
1563   modulestream = modulemd_module_stream_v1_new (NULL, NULL);
1564 
1565   /* Read the MAPPING_START */
1566   YAML_PARSER_PARSE_WITH_EXIT (&parser, &event, error);
1567   if (event.type != YAML_MAPPING_START_EVENT)
1568     {
1569       MMD_YAML_ERROR_EVENT_EXIT (
1570         error, event, "Data section did not begin with a map.");
1571     }
1572 
1573   /* Process through the mapping */
1574   while (!done)
1575     {
1576       YAML_PARSER_PARSE_WITH_EXIT (&parser, &event, error);
1577 
1578       switch (event.type)
1579         {
1580         case YAML_MAPPING_END_EVENT: done = TRUE; break;
1581 
1582         case YAML_SCALAR_EVENT:
1583           /* Mapping Keys */
1584 
1585           /* Module Name */
1586           if (g_str_equal ((const gchar *)event.data.scalar.value, "name"))
1587             {
1588               MMD_SET_PARSED_YAML_STRING (
1589                 &parser,
1590                 error,
1591                 modulemd_module_stream_set_module_name,
1592                 MODULEMD_MODULE_STREAM (modulestream));
1593             }
1594 
1595           /* Module Stream Name */
1596           else if (g_str_equal ((const gchar *)event.data.scalar.value,
1597                                 "stream"))
1598             {
1599               MMD_SET_PARSED_YAML_STRING (
1600                 &parser,
1601                 error,
1602                 modulemd_module_stream_set_stream_name,
1603                 MODULEMD_MODULE_STREAM (modulestream));
1604             }
1605 
1606           /* Module Version */
1607           else if (g_str_equal ((const gchar *)event.data.scalar.value,
1608                                 "version"))
1609             {
1610               version = modulemd_yaml_parse_uint64 (&parser, &nested_error);
1611               if (nested_error)
1612                 {
1613                   g_propagate_error (error, g_steal_pointer (&nested_error));
1614                   return NULL;
1615                 }
1616 
1617               modulemd_module_stream_set_version (
1618                 MODULEMD_MODULE_STREAM (modulestream), version);
1619             }
1620 
1621           /* Module Context */
1622           else if (g_str_equal ((const gchar *)event.data.scalar.value,
1623                                 "context"))
1624             {
1625               MMD_SET_PARSED_YAML_STRING (
1626                 &parser,
1627                 error,
1628                 modulemd_module_stream_set_context,
1629                 MODULEMD_MODULE_STREAM (modulestream));
1630             }
1631 
1632           /* Module Artifact Architecture */
1633           else if (g_str_equal ((const gchar *)event.data.scalar.value,
1634                                 "arch"))
1635             {
1636               MMD_SET_PARSED_YAML_STRING (&parser,
1637                                           error,
1638                                           modulemd_module_stream_v1_set_arch,
1639                                           modulestream);
1640             }
1641 
1642           /* Module Summary */
1643           else if (g_str_equal ((const gchar *)event.data.scalar.value,
1644                                 "summary"))
1645             {
1646               MMD_SET_PARSED_YAML_STRING (
1647                 &parser,
1648                 error,
1649                 modulemd_module_stream_v1_set_summary,
1650                 modulestream);
1651             }
1652 
1653           /* Module Description */
1654           else if (g_str_equal ((const gchar *)event.data.scalar.value,
1655                                 "description"))
1656             {
1657               MMD_SET_PARSED_YAML_STRING (
1658                 &parser,
1659                 error,
1660                 modulemd_module_stream_v1_set_description,
1661                 modulestream);
1662             }
1663 
1664           /* Service Levels */
1665           else if (g_str_equal ((const gchar *)event.data.scalar.value,
1666                                 "servicelevels"))
1667             {
1668               if (!modulemd_module_stream_v1_parse_servicelevels (
1669                     &parser, modulestream, strict, &nested_error))
1670                 {
1671                   g_propagate_error (error, g_steal_pointer (&nested_error));
1672                   return NULL;
1673                 }
1674             }
1675 
1676           /* Licences */
1677           else if (g_str_equal ((const gchar *)event.data.scalar.value,
1678                                 "license"))
1679             {
1680               if (!modulemd_module_stream_v1_parse_licenses (
1681                     &parser, modulestream, strict, &nested_error))
1682                 {
1683                   g_propagate_error (error, g_steal_pointer (&nested_error));
1684                   return NULL;
1685                 }
1686             }
1687 
1688           /* Extensible Metadata */
1689           else if (g_str_equal ((const gchar *)event.data.scalar.value, "xmd"))
1690             {
1691               xmd = mmd_parse_xmd (&parser, &nested_error);
1692               if (!xmd)
1693                 {
1694                   g_propagate_error (error, g_steal_pointer (&nested_error));
1695                   return NULL;
1696                 }
1697               modulemd_module_stream_v1_set_xmd (modulestream, xmd);
1698               g_clear_pointer (&xmd, g_variant_unref);
1699             }
1700 
1701           /* Dependencies */
1702           else if (g_str_equal ((const gchar *)event.data.scalar.value,
1703                                 "dependencies"))
1704             {
1705               if (!modulemd_module_stream_v1_parse_deps (
1706                     &parser, modulestream, strict, &nested_error))
1707                 {
1708                   g_propagate_error (error, g_steal_pointer (&nested_error));
1709                   return NULL;
1710                 }
1711             }
1712 
1713           /* References */
1714           else if (g_str_equal ((const gchar *)event.data.scalar.value,
1715                                 "references"))
1716             {
1717               if (!modulemd_module_stream_v1_parse_refs (
1718                     &parser, modulestream, strict, &nested_error))
1719                 {
1720                   g_propagate_error (error, g_steal_pointer (&nested_error));
1721                   return NULL;
1722                 }
1723             }
1724 
1725           /* Profiles */
1726           else if (g_str_equal ((const gchar *)event.data.scalar.value,
1727                                 "profiles"))
1728             {
1729               if (!modulemd_module_stream_v1_parse_profiles (
1730                     &parser, modulestream, strict, &nested_error))
1731                 {
1732                   g_propagate_error (error, g_steal_pointer (&nested_error));
1733                   return NULL;
1734                 }
1735             }
1736 
1737           /* API */
1738           else if (g_str_equal ((const gchar *)event.data.scalar.value, "api"))
1739             {
1740               set = modulemd_yaml_parse_string_set_from_map (
1741                 &parser, "rpms", strict, &nested_error);
1742               modulemd_module_stream_v1_replace_rpm_api (modulestream, set);
1743               g_clear_pointer (&set, g_hash_table_unref);
1744             }
1745 
1746           /* Filter */
1747           else if (g_str_equal ((const gchar *)event.data.scalar.value,
1748                                 "filter"))
1749             {
1750               set = modulemd_yaml_parse_string_set_from_map (
1751                 &parser, "rpms", strict, &nested_error);
1752               modulemd_module_stream_v1_replace_rpm_filters (modulestream,
1753                                                              set);
1754               g_clear_pointer (&set, g_hash_table_unref);
1755             }
1756 
1757           /* Build Options */
1758           else if (g_str_equal ((const gchar *)event.data.scalar.value,
1759                                 "buildopts"))
1760             {
1761               buildopts =
1762                 modulemd_buildopts_parse_yaml (&parser, strict, &nested_error);
1763               if (!buildopts)
1764                 {
1765                   g_propagate_error (error, g_steal_pointer (&nested_error));
1766                   return NULL;
1767                 }
1768 
1769               modulemd_module_stream_v1_set_buildopts (modulestream,
1770                                                        buildopts);
1771               g_clear_object (&buildopts);
1772             }
1773 
1774           /* Components */
1775           else if (g_str_equal ((const gchar *)event.data.scalar.value,
1776                                 "components"))
1777             {
1778               if (!modulemd_module_stream_v1_parse_components (
1779                     &parser, modulestream, strict, &nested_error))
1780                 {
1781                   g_propagate_error (error, g_steal_pointer (&nested_error));
1782                   return NULL;
1783                 }
1784             }
1785 
1786           /* Artifacts */
1787           else if (g_str_equal ((const gchar *)event.data.scalar.value,
1788                                 "artifacts"))
1789             {
1790               set = modulemd_yaml_parse_string_set_from_map (
1791                 &parser, "rpms", strict, &nested_error);
1792               if (!set)
1793                 {
1794                   g_propagate_error (error, g_steal_pointer (&nested_error));
1795                   return NULL;
1796                 }
1797               modulemd_module_stream_v1_replace_rpm_artifacts (modulestream,
1798                                                                set);
1799               g_clear_pointer (&set, g_hash_table_unref);
1800             }
1801 
1802           /* EOL (Deprecated) */
1803           else if (g_str_equal ((const gchar *)event.data.scalar.value, "eol"))
1804             {
1805               eol = modulemd_yaml_parse_date (&parser, &nested_error);
1806               if (!eol)
1807                 {
1808                   MMD_YAML_ERROR_EVENT_EXIT (
1809                     error,
1810                     event,
1811                     "Failed to parse EOL date in data: %s",
1812                     nested_error->message);
1813                 }
1814 
1815               /* We store EOL as the "rawhide" service level, according to the
1816                * spec.
1817                */
1818               sl = modulemd_service_level_new ("rawhide");
1819               modulemd_service_level_set_eol (sl, eol);
1820               modulemd_module_stream_v1_add_servicelevel (modulestream, sl);
1821 
1822               g_clear_object (&sl);
1823               g_clear_pointer (&eol, g_date_free);
1824             }
1825 
1826 
1827           /* Unknown key */
1828           else
1829             {
1830               SKIP_UNKNOWN (&parser,
1831                             NULL,
1832                             "Unexpected key in data: %s",
1833                             (const gchar *)event.data.scalar.value);
1834               break;
1835             }
1836           break;
1837 
1838 
1839         default:
1840           MMD_YAML_ERROR_EVENT_EXIT (
1841             error,
1842             event,
1843             "Unexpected YAML event in ModuleStreamV1: %s",
1844             mmd_yaml_get_event_name (event.type));
1845           break;
1846         }
1847       yaml_event_delete (&event);
1848     }
1849 
1850   return g_steal_pointer (&modulestream);
1851 }
1852 
1853 
1854 static gboolean
modulemd_module_stream_v1_parse_licenses(yaml_parser_t * parser,ModulemdModuleStreamV1 * modulestream,gboolean strict,GError ** error)1855 modulemd_module_stream_v1_parse_licenses (yaml_parser_t *parser,
1856                                           ModulemdModuleStreamV1 *modulestream,
1857                                           gboolean strict,
1858                                           GError **error)
1859 {
1860   MODULEMD_INIT_TRACE ();
1861   MMD_INIT_YAML_EVENT (event);
1862   gboolean done = FALSE;
1863   gboolean in_map = FALSE;
1864   g_autoptr (GError) nested_error = NULL;
1865   g_autoptr (GHashTable) set = NULL;
1866 
1867   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1868 
1869   /* Process through the mapping */
1870   while (!done)
1871     {
1872       YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
1873 
1874       switch (event.type)
1875         {
1876         case YAML_MAPPING_START_EVENT:
1877           if (in_map)
1878             {
1879               MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1880                 error,
1881                 event,
1882                 "Unexpected extra MAPPING_START event in licenses");
1883             }
1884           in_map = TRUE;
1885           break;
1886 
1887         case YAML_MAPPING_END_EVENT:
1888           if (!in_map)
1889             {
1890               MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1891                 error, event, "Unexpected MAPPING_END event in licenses");
1892             }
1893           done = TRUE;
1894           break;
1895 
1896         case YAML_SCALAR_EVENT:
1897           if (!in_map)
1898             {
1899               MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1900                 error, event, "Received scalar outside of mapping");
1901             }
1902 
1903           if (g_str_equal ((const gchar *)event.data.scalar.value, "module"))
1904             {
1905               set = modulemd_yaml_parse_string_set (parser, &nested_error);
1906               if (!set)
1907                 {
1908                   g_propagate_error (error, g_steal_pointer (&nested_error));
1909                   return FALSE;
1910                 }
1911               modulemd_module_stream_v1_replace_module_licenses (modulestream,
1912                                                                  set);
1913               g_clear_pointer (&set, g_hash_table_unref);
1914             }
1915           else if (g_str_equal ((const gchar *)event.data.scalar.value,
1916                                 "content"))
1917             {
1918               set = modulemd_yaml_parse_string_set (parser, &nested_error);
1919               modulemd_module_stream_v1_replace_content_licenses (modulestream,
1920                                                                   set);
1921               g_clear_pointer (&set, g_hash_table_unref);
1922             }
1923           else
1924             {
1925               SKIP_UNKNOWN (parser,
1926                             FALSE,
1927                             "Unexpected key in licenses: %s",
1928                             (const gchar *)event.data.scalar.value);
1929               break;
1930             }
1931 
1932           break;
1933 
1934         default:
1935           MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1936             error,
1937             event,
1938             "Unexpected YAML event in licenses: %s",
1939             mmd_yaml_get_event_name (event.type));
1940           break;
1941         }
1942       yaml_event_delete (&event);
1943     }
1944 
1945   return TRUE;
1946 }
1947 
1948 
1949 static gboolean
modulemd_module_stream_v1_parse_servicelevels(yaml_parser_t * parser,ModulemdModuleStreamV1 * modulestream,gboolean strict,GError ** error)1950 modulemd_module_stream_v1_parse_servicelevels (
1951   yaml_parser_t *parser,
1952   ModulemdModuleStreamV1 *modulestream,
1953   gboolean strict,
1954   GError **error)
1955 {
1956   MODULEMD_INIT_TRACE ();
1957   MMD_INIT_YAML_EVENT (event);
1958   gboolean done = FALSE;
1959   gboolean in_map = FALSE;
1960   const gchar *name = NULL;
1961   g_autoptr (ModulemdServiceLevel) sl = NULL;
1962   g_autoptr (GError) nested_error = NULL;
1963 
1964   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1965 
1966   /* Process through the mapping */
1967   while (!done)
1968     {
1969       YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
1970 
1971       switch (event.type)
1972         {
1973         case YAML_MAPPING_START_EVENT:
1974           if (in_map)
1975             {
1976               MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1977                 error,
1978                 event,
1979                 "Unexpected extra MAPPING_START event in servicelevels");
1980             }
1981           in_map = TRUE;
1982           break;
1983 
1984         case YAML_MAPPING_END_EVENT:
1985           if (!in_map)
1986             {
1987               MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1988                 error, event, "Unexpected MAPPING_END event in servicelevels");
1989             }
1990           done = TRUE;
1991           break;
1992 
1993         case YAML_SCALAR_EVENT:
1994           if (!in_map)
1995             {
1996               MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1997                 error, event, "Received scalar outside of mapping");
1998             }
1999 
2000           name = (const gchar *)event.data.scalar.value;
2001 
2002           sl = modulemd_service_level_parse_yaml (
2003             parser, name, strict, &nested_error);
2004           if (!sl)
2005             {
2006               g_propagate_error (error, g_steal_pointer (&nested_error));
2007               return FALSE;
2008             }
2009 
2010           modulemd_module_stream_v1_add_servicelevel (modulestream, sl);
2011           g_clear_object (&sl);
2012 
2013           break;
2014 
2015         default:
2016           MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2017             error,
2018             event,
2019             "Unexpected YAML event in servicelevels: %s",
2020             mmd_yaml_get_event_name (event.type));
2021           break;
2022         }
2023       yaml_event_delete (&event);
2024     }
2025 
2026   return TRUE;
2027 }
2028 
2029 static gboolean
modulemd_module_stream_v1_parse_deps(yaml_parser_t * parser,ModulemdModuleStreamV1 * modulestream,gboolean strict,GError ** error)2030 modulemd_module_stream_v1_parse_deps (yaml_parser_t *parser,
2031                                       ModulemdModuleStreamV1 *modulestream,
2032                                       gboolean strict,
2033                                       GError **error)
2034 {
2035   MODULEMD_INIT_TRACE ();
2036   MMD_INIT_YAML_EVENT (event);
2037   gboolean done = FALSE;
2038   g_autoptr (GError) nested_error = NULL;
2039   g_autoptr (GHashTable) deptable = NULL;
2040 
2041   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2042 
2043   /* Process through the sequence */
2044   /* We *must* get a MAPPING_START here */
2045   YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2046   if (event.type != YAML_MAPPING_START_EVENT)
2047     {
2048       MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2049         error,
2050         event,
2051         "Got %s instead of SEQUENCE_START in dependencies.",
2052         mmd_yaml_get_event_name (event.type));
2053     }
2054 
2055   while (!done)
2056     {
2057       YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2058 
2059       switch (event.type)
2060         {
2061         case YAML_MAPPING_END_EVENT: done = TRUE; break;
2062 
2063         case YAML_SCALAR_EVENT:
2064           if (g_str_equal ((const gchar *)event.data.scalar.value,
2065                            "buildrequires"))
2066             {
2067               deptable =
2068                 modulemd_yaml_parse_string_string_map (parser, &nested_error);
2069               if (!deptable)
2070                 {
2071                   g_propagate_error (error, g_steal_pointer (&nested_error));
2072                   return FALSE;
2073                 }
2074               modulemd_module_stream_v1_replace_buildtime_deps (modulestream,
2075                                                                 deptable);
2076               g_clear_pointer (&deptable, g_hash_table_unref);
2077             }
2078 
2079           else if (g_str_equal ((const gchar *)event.data.scalar.value,
2080                                 "requires"))
2081             {
2082               deptable =
2083                 modulemd_yaml_parse_string_string_map (parser, &nested_error);
2084               if (!deptable)
2085                 {
2086                   g_propagate_error (error, g_steal_pointer (&nested_error));
2087                   return FALSE;
2088                 }
2089               modulemd_module_stream_v1_replace_runtime_deps (modulestream,
2090                                                               deptable);
2091               g_clear_pointer (&deptable, g_hash_table_unref);
2092             }
2093 
2094           else
2095             {
2096               SKIP_UNKNOWN (parser,
2097                             FALSE,
2098                             "Unexpected key in dependencies: %s",
2099                             (const gchar *)event.data.scalar.value);
2100               break;
2101             }
2102 
2103           break;
2104 
2105         default:
2106           MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2107             error,
2108             event,
2109             "Unexpected YAML event in dependencies: %s",
2110             mmd_yaml_get_event_name (event.type));
2111           break;
2112         }
2113       yaml_event_delete (&event);
2114     }
2115 
2116   return TRUE;
2117 }
2118 
2119 
2120 static gboolean
modulemd_module_stream_v1_parse_refs(yaml_parser_t * parser,ModulemdModuleStreamV1 * modulestream,gboolean strict,GError ** error)2121 modulemd_module_stream_v1_parse_refs (yaml_parser_t *parser,
2122                                       ModulemdModuleStreamV1 *modulestream,
2123                                       gboolean strict,
2124                                       GError **error)
2125 {
2126   MODULEMD_INIT_TRACE ();
2127   MMD_INIT_YAML_EVENT (event);
2128   gboolean done = FALSE;
2129   g_autofree gchar *scalar = NULL;
2130   g_autoptr (GError) nested_error = NULL;
2131 
2132   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2133 
2134   /* Process through the map */
2135   /* We *must* get a MAPPING_START here */
2136   YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2137   if (event.type != YAML_MAPPING_START_EVENT)
2138     {
2139       MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2140         error,
2141         event,
2142         "Got %s instead of MAPPING_START in dependencies.",
2143         mmd_yaml_get_event_name (event.type));
2144     }
2145 
2146   while (!done)
2147     {
2148       YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2149 
2150       switch (event.type)
2151         {
2152         case YAML_MAPPING_END_EVENT: done = TRUE; break;
2153 
2154         case YAML_SCALAR_EVENT:
2155           if (g_str_equal ((const gchar *)event.data.scalar.value,
2156                            "community"))
2157             {
2158               scalar = modulemd_yaml_parse_string (parser, &nested_error);
2159               if (!scalar)
2160                 {
2161                   g_propagate_error (error, g_steal_pointer (&nested_error));
2162                   return FALSE;
2163                 }
2164 
2165               modulemd_module_stream_v1_set_community (modulestream, scalar);
2166               g_clear_pointer (&scalar, g_free);
2167             }
2168 
2169           else if (g_str_equal ((const gchar *)event.data.scalar.value,
2170                                 "documentation"))
2171             {
2172               scalar = modulemd_yaml_parse_string (parser, &nested_error);
2173               if (!scalar)
2174                 {
2175                   g_propagate_error (error, g_steal_pointer (&nested_error));
2176                   return FALSE;
2177                 }
2178 
2179               modulemd_module_stream_v1_set_documentation (modulestream,
2180                                                            scalar);
2181               g_clear_pointer (&scalar, g_free);
2182             }
2183 
2184           else if (g_str_equal ((const gchar *)event.data.scalar.value,
2185                                 "tracker"))
2186             {
2187               scalar = modulemd_yaml_parse_string (parser, &nested_error);
2188               if (!scalar)
2189                 {
2190                   g_propagate_error (error, g_steal_pointer (&nested_error));
2191                   return FALSE;
2192                 }
2193 
2194               modulemd_module_stream_v1_set_tracker (modulestream, scalar);
2195               g_clear_pointer (&scalar, g_free);
2196             }
2197 
2198           else
2199             {
2200               SKIP_UNKNOWN (parser,
2201                             FALSE,
2202                             "Unexpected key in references: %s",
2203                             (const gchar *)event.data.scalar.value);
2204               break;
2205             }
2206           break;
2207 
2208         default:
2209           MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2210             error,
2211             event,
2212             "Unexpected YAML event in dependencies: %s",
2213             mmd_yaml_get_event_name (event.type));
2214           break;
2215         }
2216       yaml_event_delete (&event);
2217     }
2218 
2219   return TRUE;
2220 }
2221 
2222 
2223 static gboolean
modulemd_module_stream_v1_parse_profiles(yaml_parser_t * parser,ModulemdModuleStreamV1 * modulestream,gboolean strict,GError ** error)2224 modulemd_module_stream_v1_parse_profiles (yaml_parser_t *parser,
2225                                           ModulemdModuleStreamV1 *modulestream,
2226                                           gboolean strict,
2227                                           GError **error)
2228 {
2229   MODULEMD_INIT_TRACE ();
2230   MMD_INIT_YAML_EVENT (event);
2231   gboolean done = FALSE;
2232   g_autoptr (GError) nested_error = NULL;
2233   g_autoptr (ModulemdProfile) profile = NULL;
2234 
2235   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2236 
2237   /* Process through the map */
2238   /* We *must* get a MAPPING_START here */
2239   YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2240   if (event.type != YAML_MAPPING_START_EVENT)
2241     {
2242       MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2243         error,
2244         event,
2245         "Got %s instead of MAPPING_START in profiles.",
2246         mmd_yaml_get_event_name (event.type));
2247     }
2248 
2249   while (!done)
2250     {
2251       YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2252 
2253       switch (event.type)
2254         {
2255         case YAML_MAPPING_END_EVENT: done = TRUE; break;
2256 
2257         case YAML_SCALAR_EVENT:
2258           profile = modulemd_profile_parse_yaml (
2259             parser,
2260             (const gchar *)event.data.scalar.value,
2261             strict,
2262             &nested_error);
2263           if (!profile)
2264             {
2265               g_propagate_error (error, g_steal_pointer (&nested_error));
2266               return FALSE;
2267             }
2268 
2269           modulemd_module_stream_v1_add_profile (modulestream, profile);
2270           g_clear_pointer (&profile, g_object_unref);
2271           break;
2272 
2273         default:
2274           MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2275             error,
2276             event,
2277             "Unexpected YAML event in dependencies: %s",
2278             mmd_yaml_get_event_name (event.type));
2279           break;
2280         }
2281       yaml_event_delete (&event);
2282     }
2283 
2284   return TRUE;
2285 }
2286 
2287 
2288 static gboolean
2289 modulemd_module_stream_v1_parse_rpm_components (
2290   yaml_parser_t *parser,
2291   ModulemdModuleStreamV1 *modulestream,
2292   gboolean strict,
2293   GError **error);
2294 static gboolean
2295 modulemd_module_stream_v1_parse_module_components (
2296   yaml_parser_t *parser,
2297   ModulemdModuleStreamV1 *modulestream,
2298   gboolean strict,
2299   GError **error);
2300 
2301 
2302 static gboolean
modulemd_module_stream_v1_parse_components(yaml_parser_t * parser,ModulemdModuleStreamV1 * modulestream,gboolean strict,GError ** error)2303 modulemd_module_stream_v1_parse_components (
2304   yaml_parser_t *parser,
2305   ModulemdModuleStreamV1 *modulestream,
2306   gboolean strict,
2307   GError **error)
2308 {
2309   MODULEMD_INIT_TRACE ();
2310   MMD_INIT_YAML_EVENT (event);
2311   gboolean done = FALSE;
2312   g_autoptr (GError) nested_error = NULL;
2313 
2314   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2315 
2316   /* Process through the sequence */
2317   /* We *must* get a MAPPING_START here */
2318   YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2319   if (event.type != YAML_MAPPING_START_EVENT)
2320     {
2321       MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2322         error,
2323         event,
2324         "Got %s instead of MAPPING_START in components.",
2325         mmd_yaml_get_event_name (event.type));
2326     }
2327 
2328   while (!done)
2329     {
2330       YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2331 
2332       switch (event.type)
2333         {
2334         case YAML_MAPPING_END_EVENT: done = TRUE; break;
2335 
2336         case YAML_SCALAR_EVENT:
2337           if (g_str_equal ((const gchar *)event.data.scalar.value, "rpms"))
2338             {
2339               if (!modulemd_module_stream_v1_parse_rpm_components (
2340                     parser, modulestream, strict, &nested_error))
2341                 {
2342                   g_propagate_error (error, g_steal_pointer (&nested_error));
2343                   return FALSE;
2344                 }
2345             }
2346           else if (g_str_equal ((const gchar *)event.data.scalar.value,
2347                                 "modules"))
2348             {
2349               if (!modulemd_module_stream_v1_parse_module_components (
2350                     parser, modulestream, strict, &nested_error))
2351                 {
2352                   g_propagate_error (error, g_steal_pointer (&nested_error));
2353                   return FALSE;
2354                 }
2355             }
2356 
2357           else
2358             {
2359               SKIP_UNKNOWN (parser,
2360                             FALSE,
2361                             "Unexpected key in components: %s",
2362                             (const gchar *)event.data.scalar.value);
2363               break;
2364             }
2365 
2366           break;
2367 
2368 
2369         default:
2370           MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2371             error,
2372             event,
2373             "Unexpected YAML event in components: %s",
2374             mmd_yaml_get_event_name (event.type));
2375           break;
2376         }
2377       yaml_event_delete (&event);
2378     }
2379 
2380   return TRUE;
2381 }
2382 
2383 
2384 static gboolean
modulemd_module_stream_v1_parse_rpm_components(yaml_parser_t * parser,ModulemdModuleStreamV1 * modulestream,gboolean strict,GError ** error)2385 modulemd_module_stream_v1_parse_rpm_components (
2386   yaml_parser_t *parser,
2387   ModulemdModuleStreamV1 *modulestream,
2388   gboolean strict,
2389   GError **error)
2390 {
2391   MODULEMD_INIT_TRACE ();
2392   MMD_INIT_YAML_EVENT (event);
2393   gboolean done = FALSE;
2394   g_autoptr (GError) nested_error = NULL;
2395   g_autoptr (ModulemdComponentRpm) component = NULL;
2396 
2397   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2398 
2399   /* We *must* get a MAPPING_START here */
2400   YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2401   if (event.type != YAML_MAPPING_START_EVENT)
2402     {
2403       MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2404         error,
2405         event,
2406         "Got %s instead of MAPPING_START in rpm components.",
2407         mmd_yaml_get_event_name (event.type));
2408     }
2409 
2410   while (!done)
2411     {
2412       YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2413 
2414       switch (event.type)
2415         {
2416         case YAML_MAPPING_END_EVENT: done = TRUE; break;
2417 
2418         case YAML_SCALAR_EVENT:
2419           component = modulemd_component_rpm_parse_yaml (
2420             parser,
2421             (const gchar *)event.data.scalar.value,
2422             strict,
2423             &nested_error);
2424           if (!component)
2425             {
2426               g_propagate_error (error, g_steal_pointer (&nested_error));
2427               return FALSE;
2428             }
2429           modulemd_module_stream_v1_add_component (
2430             modulestream, (ModulemdComponent *)component);
2431           g_clear_pointer (&component, g_object_unref);
2432           break;
2433 
2434         default:
2435           MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2436             error,
2437             event,
2438             "Unexpected YAML event in RPM component: %s",
2439             mmd_yaml_get_event_name (event.type));
2440           break;
2441         }
2442       yaml_event_delete (&event);
2443     }
2444 
2445   return TRUE;
2446 }
2447 
2448 
2449 static gboolean
modulemd_module_stream_v1_parse_module_components(yaml_parser_t * parser,ModulemdModuleStreamV1 * modulestream,gboolean strict,GError ** error)2450 modulemd_module_stream_v1_parse_module_components (
2451   yaml_parser_t *parser,
2452   ModulemdModuleStreamV1 *modulestream,
2453   gboolean strict,
2454   GError **error)
2455 {
2456   MODULEMD_INIT_TRACE ();
2457   MMD_INIT_YAML_EVENT (event);
2458   gboolean done = FALSE;
2459   g_autoptr (GError) nested_error = NULL;
2460   g_autoptr (ModulemdComponentModule) component = NULL;
2461 
2462   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2463 
2464   /* We *must* get a MAPPING_START here */
2465   YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2466   if (event.type != YAML_MAPPING_START_EVENT)
2467     {
2468       MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2469         error,
2470         event,
2471         "Got %s instead of MAPPING_START in module components.",
2472         mmd_yaml_get_event_name (event.type));
2473     }
2474 
2475   while (!done)
2476     {
2477       YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2478 
2479       switch (event.type)
2480         {
2481         case YAML_MAPPING_END_EVENT: done = TRUE; break;
2482 
2483         case YAML_SCALAR_EVENT:
2484           component = modulemd_component_module_parse_yaml (
2485             parser,
2486             (const gchar *)event.data.scalar.value,
2487             strict,
2488             &nested_error);
2489           if (!component)
2490             {
2491               g_propagate_error (error, g_steal_pointer (&nested_error));
2492               return FALSE;
2493             }
2494           modulemd_module_stream_v1_add_component (
2495             modulestream, (ModulemdComponent *)component);
2496           g_clear_pointer (&component, g_object_unref);
2497           break;
2498 
2499         default:
2500           MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2501             error,
2502             event,
2503             "Unexpected YAML event in module component: %s",
2504             mmd_yaml_get_event_name (event.type));
2505           break;
2506         }
2507       yaml_event_delete (&event);
2508     }
2509 
2510   return TRUE;
2511 }
2512 
2513 
2514 gboolean
modulemd_module_stream_v1_emit_yaml(ModulemdModuleStreamV1 * self,yaml_emitter_t * emitter,GError ** error)2515 modulemd_module_stream_v1_emit_yaml (ModulemdModuleStreamV1 *self,
2516                                      yaml_emitter_t *emitter,
2517                                      GError **error)
2518 {
2519   MODULEMD_INIT_TRACE ();
2520   if (!modulemd_module_stream_emit_yaml_base (
2521         MODULEMD_MODULE_STREAM (self), emitter, error))
2522     {
2523       return FALSE;
2524     }
2525 
2526   EMIT_KEY_VALUE_IF_SET (
2527     emitter, error, "arch", modulemd_module_stream_v1_get_arch (self));
2528   EMIT_KEY_VALUE (emitter, error, "summary", self->summary);
2529   EMIT_KEY_VALUE_FULL (emitter,
2530                        error,
2531                        "description",
2532                        self->description,
2533                        YAML_FOLDED_SCALAR_STYLE);
2534 
2535   EMIT_HASHTABLE_VALUES_IF_NON_EMPTY (emitter,
2536                                       error,
2537                                       "servicelevels",
2538                                       self->servicelevels,
2539                                       modulemd_service_level_emit_yaml);
2540 
2541   if (!NON_EMPTY_TABLE (self->module_licenses))
2542     {
2543       g_set_error (error,
2544                    MODULEMD_YAML_ERROR,
2545                    MMD_YAML_ERROR_EMIT,
2546                    "Module licenses is not allowed to be empty");
2547       return FALSE;
2548     }
2549 
2550   EMIT_SCALAR (emitter, error, "license");
2551   EMIT_MAPPING_START (emitter, error);
2552   EMIT_STRING_SET (emitter, error, "module", self->module_licenses);
2553   EMIT_STRING_SET_IF_NON_EMPTY (
2554     emitter, error, "content", self->content_licenses);
2555   EMIT_MAPPING_END (emitter, error);
2556 
2557   if (self->xmd != NULL)
2558     {
2559       EMIT_SCALAR (emitter, error, "xmd");
2560       if (!modulemd_yaml_emit_variant (emitter, self->xmd, error))
2561         {
2562           return FALSE;
2563         }
2564     }
2565 
2566   if (NON_EMPTY_TABLE (self->buildtime_deps) ||
2567       NON_EMPTY_TABLE (self->runtime_deps))
2568     {
2569       EMIT_SCALAR (emitter, error, "dependencies");
2570       EMIT_MAPPING_START (emitter, error);
2571       EMIT_HASHTABLE_KEY_VALUES_IF_NON_EMPTY (
2572         emitter, error, "buildrequires", self->buildtime_deps);
2573       EMIT_HASHTABLE_KEY_VALUES_IF_NON_EMPTY (
2574         emitter, error, "requires", self->runtime_deps);
2575       EMIT_MAPPING_END (emitter, error);
2576     }
2577 
2578   if (self->community || self->documentation || self->tracker)
2579     {
2580       EMIT_SCALAR (emitter, error, "references");
2581       EMIT_MAPPING_START (emitter, error);
2582       EMIT_KEY_VALUE_IF_SET (emitter, error, "community", self->community);
2583       EMIT_KEY_VALUE_IF_SET (
2584         emitter, error, "documentation", self->documentation);
2585       EMIT_KEY_VALUE_IF_SET (emitter, error, "tracker", self->tracker);
2586       EMIT_MAPPING_END (emitter, error);
2587     }
2588 
2589   EMIT_HASHTABLE_VALUES_IF_NON_EMPTY (
2590     emitter, error, "profiles", self->profiles, modulemd_profile_emit_yaml);
2591 
2592   if (NON_EMPTY_TABLE (self->rpm_api))
2593     {
2594       EMIT_SCALAR (emitter, error, "api");
2595       EMIT_MAPPING_START (emitter, error);
2596       EMIT_STRING_SET (emitter, error, "rpms", self->rpm_api);
2597       EMIT_MAPPING_END (emitter, error);
2598     }
2599 
2600   if (NON_EMPTY_TABLE (self->rpm_filters))
2601     {
2602       EMIT_SCALAR (emitter, error, "filter");
2603       EMIT_MAPPING_START (emitter, error);
2604       EMIT_STRING_SET (emitter, error, "rpms", self->rpm_filters);
2605       EMIT_MAPPING_END (emitter, error);
2606     }
2607 
2608   if (self->buildopts != NULL)
2609     {
2610       EMIT_SCALAR (emitter, error, "buildopts");
2611       EMIT_MAPPING_START (emitter, error);
2612       if (!modulemd_buildopts_emit_yaml (self->buildopts, emitter, error))
2613         {
2614           return FALSE;
2615         }
2616       EMIT_MAPPING_END (emitter, error);
2617     }
2618 
2619   if (NON_EMPTY_TABLE (self->rpm_components) ||
2620       NON_EMPTY_TABLE (self->module_components))
2621     {
2622       EMIT_SCALAR (emitter, error, "components");
2623       EMIT_MAPPING_START (emitter, error);
2624       EMIT_HASHTABLE_VALUES_IF_NON_EMPTY (emitter,
2625                                           error,
2626                                           "rpms",
2627                                           self->rpm_components,
2628                                           modulemd_component_rpm_emit_yaml);
2629       EMIT_HASHTABLE_VALUES_IF_NON_EMPTY (emitter,
2630                                           error,
2631                                           "modules",
2632                                           self->module_components,
2633                                           modulemd_component_module_emit_yaml);
2634       EMIT_MAPPING_END (emitter, error);
2635     }
2636 
2637   if (NON_EMPTY_TABLE (self->rpm_artifacts))
2638     {
2639       EMIT_SCALAR (emitter, error, "artifacts");
2640       EMIT_MAPPING_START (emitter, error);
2641       EMIT_STRING_SET (emitter, error, "rpms", self->rpm_artifacts);
2642       EMIT_MAPPING_END (emitter, error);
2643     }
2644 
2645   /* The "data" mapping */
2646   EMIT_MAPPING_END (emitter, error);
2647   /* The overall document mapping */
2648   EMIT_MAPPING_END (emitter, error);
2649   if (!mmd_emitter_end_document (emitter, error))
2650     {
2651       return FALSE;
2652     }
2653 
2654   return TRUE;
2655 }
2656