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-v2.h"
20 #include "modulemd-module-stream.h"
21 #include "modulemd-profile.h"
22 #include "modulemd-rpm-map-entry.h"
23 #include "modulemd-service-level.h"
24 #include "modulemd-translation-entry.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-dependencies-private.h"
30 #include "private/modulemd-module-stream-private.h"
31 #include "private/modulemd-module-stream-v2-private.h"
32 #include "private/modulemd-profile-private.h"
33 #include "private/modulemd-rpm-map-entry-private.h"
34 #include "private/modulemd-service-level-private.h"
35 #include "private/modulemd-subdocument-info-private.h"
36 #include "private/modulemd-util.h"
37 #include "private/modulemd-yaml.h"
38
39
40 G_DEFINE_TYPE (ModulemdModuleStreamV2,
41 modulemd_module_stream_v2,
42 MODULEMD_TYPE_MODULE_STREAM)
43
44 enum
45 {
46 PROP_0,
47 PROP_ARCH,
48 PROP_BUILDOPTS,
49 PROP_COMMUNITY,
50 PROP_DOCUMENTATION,
51 PROP_TRACKER,
52 PROP_STATIC_CONTEXT,
53 N_PROPS
54 };
55
56 static GParamSpec *properties[N_PROPS];
57
58 ModulemdModuleStreamV2 *
modulemd_module_stream_v2_new(const gchar * module_name,const gchar * module_stream)59 modulemd_module_stream_v2_new (const gchar *module_name,
60 const gchar *module_stream)
61 {
62 // clang-format off
63 return g_object_new (MODULEMD_TYPE_MODULE_STREAM_V2,
64 "module-name", module_name,
65 "stream-name", module_stream,
66 NULL);
67 // clang-format on
68 }
69
70
71 static void
modulemd_module_stream_v2_finalize(GObject * object)72 modulemd_module_stream_v2_finalize (GObject *object)
73 {
74 ModulemdModuleStreamV2 *self = MODULEMD_MODULE_STREAM_V2 (object);
75
76 /* Properties */
77 g_clear_object (&self->buildopts);
78 g_clear_pointer (&self->community, g_free);
79 g_clear_pointer (&self->description, g_free);
80 g_clear_pointer (&self->documentation, g_free);
81 g_clear_pointer (&self->summary, g_free);
82 g_clear_pointer (&self->tracker, g_free);
83
84 /* Internal Data Structures */
85 g_clear_pointer (&self->module_components, g_hash_table_unref);
86 g_clear_pointer (&self->rpm_components, g_hash_table_unref);
87
88 g_clear_pointer (&self->content_licenses, g_hash_table_unref);
89 g_clear_pointer (&self->module_licenses, g_hash_table_unref);
90
91 g_clear_pointer (&self->profiles, g_hash_table_unref);
92
93 g_clear_pointer (&self->rpm_api, g_hash_table_unref);
94
95 g_clear_pointer (&self->rpm_artifacts, g_hash_table_unref);
96
97 g_clear_pointer (&self->rpm_artifact_map, g_hash_table_unref);
98
99 g_clear_pointer (&self->rpm_filters, g_hash_table_unref);
100
101 g_clear_pointer (&self->demodularized_rpms, g_hash_table_unref);
102
103 g_clear_pointer (&self->servicelevels, g_hash_table_unref);
104
105 g_clear_pointer (&self->dependencies, g_ptr_array_unref);
106
107 g_clear_pointer (&self->obsoletes, g_object_unref);
108
109 g_clear_pointer (&self->xmd, g_variant_unref);
110
111 G_OBJECT_CLASS (modulemd_module_stream_v2_parent_class)->finalize (object);
112 }
113
114
115 static gboolean
modulemd_module_stream_v2_equals(ModulemdModuleStream * self_1,ModulemdModuleStream * self_2)116 modulemd_module_stream_v2_equals (ModulemdModuleStream *self_1,
117 ModulemdModuleStream *self_2)
118 {
119 ModulemdModuleStreamV2 *v2_self_1 = NULL;
120 ModulemdModuleStreamV2 *v2_self_2 = NULL;
121
122 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self_1), FALSE);
123 v2_self_1 = MODULEMD_MODULE_STREAM_V2 (self_1);
124 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self_2), FALSE);
125 v2_self_2 = MODULEMD_MODULE_STREAM_V2 (self_2);
126
127 if (!MODULEMD_MODULE_STREAM_CLASS (modulemd_module_stream_v2_parent_class)
128 ->equals (self_1, self_2))
129 {
130 return FALSE;
131 }
132
133 /*Check property equality*/
134 if (g_strcmp0 (v2_self_1->community, v2_self_2->community) != 0)
135 {
136 return FALSE;
137 }
138
139 if (g_strcmp0 (v2_self_1->description, v2_self_2->description) != 0)
140 {
141 return FALSE;
142 }
143
144 if (g_strcmp0 (v2_self_1->documentation, v2_self_2->documentation) != 0)
145 {
146 return FALSE;
147 }
148
149 if (g_strcmp0 (v2_self_1->summary, v2_self_2->summary) != 0)
150 {
151 return FALSE;
152 }
153
154 if (g_strcmp0 (v2_self_1->tracker, v2_self_2->tracker) != 0)
155 {
156 return FALSE;
157 }
158
159 /* Test the negations of static_context just in case somehow they are
160 * different non-zero values
161 */
162 if (!v2_self_1->static_context != !v2_self_2->static_context)
163 {
164 return FALSE;
165 }
166
167 if (!modulemd_buildopts_equals (v2_self_1->buildopts, v2_self_2->buildopts))
168 {
169 return FALSE;
170 }
171
172 if (!modulemd_hash_table_equals (v2_self_1->rpm_components,
173 v2_self_2->rpm_components,
174 modulemd_component_equals_wrapper))
175 {
176 return FALSE;
177 }
178
179 if (!modulemd_hash_table_equals (v2_self_1->module_components,
180 v2_self_2->module_components,
181 modulemd_component_equals_wrapper))
182 {
183 return FALSE;
184 }
185
186 if (!modulemd_hash_table_sets_are_equal (v2_self_1->module_licenses,
187 v2_self_2->module_licenses))
188 {
189 return FALSE;
190 }
191
192 if (!modulemd_hash_table_sets_are_equal (v2_self_1->content_licenses,
193 v2_self_2->content_licenses))
194 {
195 return FALSE;
196 }
197
198 if (!modulemd_hash_table_equals (v2_self_1->profiles,
199 v2_self_2->profiles,
200 modulemd_profile_equals_wrapper))
201 {
202 return FALSE;
203 }
204
205 if (!modulemd_hash_table_sets_are_equal (v2_self_1->rpm_api,
206 v2_self_2->rpm_api))
207 {
208 return FALSE;
209 }
210
211 if (!modulemd_hash_table_sets_are_equal (v2_self_1->rpm_artifacts,
212 v2_self_2->rpm_artifacts))
213 {
214 return FALSE;
215 }
216
217 if (!modulemd_hash_table_sets_are_equal (v2_self_1->rpm_filters,
218 v2_self_2->rpm_filters))
219 {
220 return FALSE;
221 }
222
223 if (!modulemd_hash_table_sets_are_equal (v2_self_1->demodularized_rpms,
224 v2_self_2->demodularized_rpms))
225 {
226 return FALSE;
227 }
228
229 if (!modulemd_hash_table_equals (v2_self_1->servicelevels,
230 v2_self_2->servicelevels,
231 modulemd_service_level_equals_wrapper))
232 {
233 return FALSE;
234 }
235
236
237 /* < string, GHashTable <string, Modulemd.RpmMapEntry> > */
238 if (!modulemd_hash_table_equals (
239 v2_self_1->rpm_artifact_map,
240 v2_self_2->rpm_artifact_map,
241 modulemd_RpmMapEntry_hash_table_equals_wrapper))
242 {
243 return FALSE;
244 }
245
246
247 if (v2_self_1->dependencies->len != v2_self_2->dependencies->len)
248 {
249 return FALSE;
250 }
251
252 for (guint i = 0; i < v2_self_1->dependencies->len; i++)
253 {
254 /*Ordering is important for the dependencies,
255 so that each array index must be the same.*/
256 if (!modulemd_dependencies_equals (
257 g_ptr_array_index (v2_self_1->dependencies, i),
258 g_ptr_array_index (v2_self_2->dependencies, i)))
259 {
260 return FALSE;
261 }
262 }
263
264 if (v2_self_1->xmd == NULL && v2_self_2->xmd == NULL)
265 {
266 return TRUE;
267 }
268
269 if (v2_self_1->xmd == NULL || v2_self_2->xmd == NULL)
270 {
271 return FALSE;
272 }
273
274 if (!g_variant_equal (v2_self_1->xmd, v2_self_2->xmd))
275 {
276 return FALSE;
277 }
278
279 return TRUE;
280 }
281
282
283 static guint64
modulemd_module_stream_v2_get_mdversion(ModulemdModuleStream * self)284 modulemd_module_stream_v2_get_mdversion (ModulemdModuleStream *self)
285 {
286 return MD_MODULESTREAM_VERSION_TWO;
287 }
288
289
290 void
modulemd_module_stream_v2_set_arch(ModulemdModuleStreamV2 * self,const gchar * arch)291 modulemd_module_stream_v2_set_arch (ModulemdModuleStreamV2 *self,
292 const gchar *arch)
293 {
294 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
295
296 modulemd_module_stream_set_arch (MODULEMD_MODULE_STREAM (self), arch);
297
298 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ARCH]);
299 }
300
301
302 const gchar *
modulemd_module_stream_v2_get_arch(ModulemdModuleStreamV2 * self)303 modulemd_module_stream_v2_get_arch (ModulemdModuleStreamV2 *self)
304 {
305 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
306
307 return modulemd_module_stream_get_arch (MODULEMD_MODULE_STREAM (self));
308 }
309
310
311 void
modulemd_module_stream_v2_set_buildopts(ModulemdModuleStreamV2 * self,ModulemdBuildopts * buildopts)312 modulemd_module_stream_v2_set_buildopts (ModulemdModuleStreamV2 *self,
313 ModulemdBuildopts *buildopts)
314 {
315 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
316
317 g_clear_object (&self->buildopts);
318 if (buildopts)
319 {
320 self->buildopts = modulemd_buildopts_copy (buildopts);
321 }
322
323 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BUILDOPTS]);
324 }
325
326
327 ModulemdBuildopts *
modulemd_module_stream_v2_get_buildopts(ModulemdModuleStreamV2 * self)328 modulemd_module_stream_v2_get_buildopts (ModulemdModuleStreamV2 *self)
329 {
330 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
331
332 return self->buildopts;
333 }
334
335
336 void
modulemd_module_stream_v2_set_community(ModulemdModuleStreamV2 * self,const gchar * community)337 modulemd_module_stream_v2_set_community (ModulemdModuleStreamV2 *self,
338 const gchar *community)
339 {
340 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
341
342 g_clear_pointer (&self->community, g_free);
343 self->community = g_strdup (community);
344
345 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COMMUNITY]);
346 }
347
348
349 const gchar *
modulemd_module_stream_v2_get_community(ModulemdModuleStreamV2 * self)350 modulemd_module_stream_v2_get_community (ModulemdModuleStreamV2 *self)
351 {
352 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
353
354 return self->community;
355 }
356
357
358 void
modulemd_module_stream_v2_set_description(ModulemdModuleStreamV2 * self,const gchar * description)359 modulemd_module_stream_v2_set_description (ModulemdModuleStreamV2 *self,
360 const gchar *description)
361 {
362 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
363
364 g_clear_pointer (&self->description, g_free);
365 self->description = g_strdup (description);
366 }
367
368
369 const gchar *
modulemd_module_stream_v2_get_description(ModulemdModuleStreamV2 * self,const gchar * locale)370 modulemd_module_stream_v2_get_description (ModulemdModuleStreamV2 *self,
371 const gchar *locale)
372 {
373 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
374
375 ModulemdTranslationEntry *entry =
376 modulemd_module_stream_get_translation_entry (
377 MODULEMD_MODULE_STREAM (self), locale);
378 if (entry != NULL &&
379 modulemd_translation_entry_get_description (entry) != NULL)
380 {
381 return modulemd_translation_entry_get_description (entry);
382 }
383
384 return self->description;
385 }
386
387
388 void
modulemd_module_stream_v2_set_documentation(ModulemdModuleStreamV2 * self,const gchar * documentation)389 modulemd_module_stream_v2_set_documentation (ModulemdModuleStreamV2 *self,
390 const gchar *documentation)
391 {
392 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
393
394 g_clear_pointer (&self->documentation, g_free);
395 self->documentation = g_strdup (documentation);
396
397 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COMMUNITY]);
398 }
399
400
401 const gchar *
modulemd_module_stream_v2_get_documentation(ModulemdModuleStreamV2 * self)402 modulemd_module_stream_v2_get_documentation (ModulemdModuleStreamV2 *self)
403 {
404 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
405
406 return self->documentation;
407 }
408
409
410 void
modulemd_module_stream_v2_set_summary(ModulemdModuleStreamV2 * self,const gchar * summary)411 modulemd_module_stream_v2_set_summary (ModulemdModuleStreamV2 *self,
412 const gchar *summary)
413 {
414 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
415
416 g_clear_pointer (&self->summary, g_free);
417 self->summary = g_strdup (summary);
418 }
419
420
421 const gchar *
modulemd_module_stream_v2_get_summary(ModulemdModuleStreamV2 * self,const gchar * locale)422 modulemd_module_stream_v2_get_summary (ModulemdModuleStreamV2 *self,
423 const gchar *locale)
424 {
425 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
426
427 ModulemdTranslationEntry *entry =
428 modulemd_module_stream_get_translation_entry (
429 MODULEMD_MODULE_STREAM (self), locale);
430 if (entry != NULL && modulemd_translation_entry_get_summary (entry) != NULL)
431 {
432 return modulemd_translation_entry_get_summary (entry);
433 }
434
435 return self->summary;
436 }
437
438
439 void
modulemd_module_stream_v2_set_tracker(ModulemdModuleStreamV2 * self,const gchar * tracker)440 modulemd_module_stream_v2_set_tracker (ModulemdModuleStreamV2 *self,
441 const gchar *tracker)
442 {
443 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
444
445 g_clear_pointer (&self->tracker, g_free);
446 self->tracker = g_strdup (tracker);
447
448 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TRACKER]);
449 }
450
451
452 const gchar *
modulemd_module_stream_v2_get_tracker(ModulemdModuleStreamV2 * self)453 modulemd_module_stream_v2_get_tracker (ModulemdModuleStreamV2 *self)
454 {
455 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
456
457 return self->tracker;
458 }
459
460
461 ModulemdObsoletes *
modulemd_module_stream_v2_get_obsoletes_resolved(ModulemdModuleStreamV2 * self)462 modulemd_module_stream_v2_get_obsoletes_resolved (ModulemdModuleStreamV2 *self)
463 {
464 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
465
466 ModulemdObsoletes *o = self->obsoletes;
467 if (o && modulemd_obsoletes_get_reset (o))
468 {
469 return NULL;
470 }
471
472 return o;
473 }
474
475 void
modulemd_module_stream_v2_associate_obsoletes(ModulemdModuleStreamV2 * self,ModulemdObsoletes * obsoletes)476 modulemd_module_stream_v2_associate_obsoletes (ModulemdModuleStreamV2 *self,
477 ModulemdObsoletes *obsoletes)
478 {
479 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
480
481 g_clear_pointer (&self->obsoletes, g_object_unref);
482 if (obsoletes != NULL)
483 {
484 self->obsoletes = g_object_ref (obsoletes);
485 }
486 }
487
488 ModulemdObsoletes *
modulemd_module_stream_v2_get_obsoletes(ModulemdModuleStreamV2 * self)489 modulemd_module_stream_v2_get_obsoletes (ModulemdModuleStreamV2 *self)
490 {
491 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
492
493 return self->obsoletes;
494 }
495
496
497 /* ===== Non-property Methods ===== */
498
499 void
modulemd_module_stream_v2_add_component(ModulemdModuleStreamV2 * self,ModulemdComponent * component)500 modulemd_module_stream_v2_add_component (ModulemdModuleStreamV2 *self,
501 ModulemdComponent *component)
502 {
503 GHashTable *table = NULL;
504
505 /* Do nothing if we were passed a NULL component */
506 if (!component)
507 {
508 return;
509 }
510
511 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
512 g_return_if_fail (MODULEMD_IS_COMPONENT (component));
513
514 if (MODULEMD_IS_COMPONENT_RPM (component))
515 {
516 table = self->rpm_components;
517 }
518 else if (MODULEMD_IS_COMPONENT_MODULE (component))
519 {
520 table = self->module_components;
521 }
522 else
523 {
524 /* Unknown component. Raise a warning and return */
525 g_return_if_reached ();
526 }
527
528 /* Add the component to the table. This will replace an existing component
529 * with the same name
530 */
531 g_hash_table_replace (table,
532 g_strdup (modulemd_component_get_key (component)),
533 modulemd_component_copy (component, NULL));
534 }
535
536
537 void
modulemd_module_stream_v2_remove_module_component(ModulemdModuleStreamV2 * self,const gchar * component_name)538 modulemd_module_stream_v2_remove_module_component (
539 ModulemdModuleStreamV2 *self, const gchar *component_name)
540 {
541 /* Do nothing if we were passed a NULL component_name */
542 if (!component_name)
543 {
544 return;
545 }
546
547 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
548
549 g_hash_table_remove (self->module_components, component_name);
550 }
551
552
553 void
modulemd_module_stream_v2_clear_module_components(ModulemdModuleStreamV2 * self)554 modulemd_module_stream_v2_clear_module_components (
555 ModulemdModuleStreamV2 *self)
556 {
557 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
558
559 g_hash_table_remove_all (self->module_components);
560 }
561
562
563 void
modulemd_module_stream_v2_remove_rpm_component(ModulemdModuleStreamV2 * self,const gchar * component_name)564 modulemd_module_stream_v2_remove_rpm_component (ModulemdModuleStreamV2 *self,
565 const gchar *component_name)
566 {
567 /* Do nothing if we were passed a NULL component_name */
568 if (!component_name)
569 {
570 return;
571 }
572
573 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
574
575 g_hash_table_remove (self->rpm_components, component_name);
576 }
577
578
579 void
modulemd_module_stream_v2_clear_rpm_components(ModulemdModuleStreamV2 * self)580 modulemd_module_stream_v2_clear_rpm_components (ModulemdModuleStreamV2 *self)
581 {
582 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
583
584 g_hash_table_remove_all (self->rpm_components);
585 }
586
587
588 GStrv
modulemd_module_stream_v2_get_module_component_names_as_strv(ModulemdModuleStreamV2 * self)589 modulemd_module_stream_v2_get_module_component_names_as_strv (
590 ModulemdModuleStreamV2 *self)
591 {
592 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
593
594 return modulemd_ordered_str_keys_as_strv (self->module_components);
595 }
596
597
598 GStrv
modulemd_module_stream_v2_get_rpm_component_names_as_strv(ModulemdModuleStreamV2 * self)599 modulemd_module_stream_v2_get_rpm_component_names_as_strv (
600 ModulemdModuleStreamV2 *self)
601 {
602 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
603
604 return modulemd_ordered_str_keys_as_strv (self->rpm_components);
605 }
606
607
608 ModulemdComponentModule *
modulemd_module_stream_v2_get_module_component(ModulemdModuleStreamV2 * self,const gchar * component_name)609 modulemd_module_stream_v2_get_module_component (ModulemdModuleStreamV2 *self,
610 const gchar *component_name)
611 {
612 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
613
614 return g_hash_table_lookup (self->module_components, component_name);
615 }
616
617
618 ModulemdComponentRpm *
modulemd_module_stream_v2_get_rpm_component(ModulemdModuleStreamV2 * self,const gchar * component_name)619 modulemd_module_stream_v2_get_rpm_component (ModulemdModuleStreamV2 *self,
620 const gchar *component_name)
621 {
622 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
623
624 return g_hash_table_lookup (self->rpm_components, component_name);
625 }
626
627
628 void
modulemd_module_stream_v2_add_content_license(ModulemdModuleStreamV2 * self,const gchar * license)629 modulemd_module_stream_v2_add_content_license (ModulemdModuleStreamV2 *self,
630 const gchar *license)
631 {
632 if (!license)
633 {
634 return;
635 }
636
637 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
638
639 g_hash_table_add (self->content_licenses, g_strdup (license));
640 }
641
642
643 void
modulemd_module_stream_v2_replace_content_licenses(ModulemdModuleStreamV2 * self,GHashTable * set)644 modulemd_module_stream_v2_replace_content_licenses (
645 ModulemdModuleStreamV2 *self, GHashTable *set)
646 {
647 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
648
649 MODULEMD_REPLACE_SET (self->content_licenses, set);
650 }
651
652
653 void
modulemd_module_stream_v2_add_module_license(ModulemdModuleStreamV2 * self,const gchar * license)654 modulemd_module_stream_v2_add_module_license (ModulemdModuleStreamV2 *self,
655 const gchar *license)
656 {
657 if (!license)
658 {
659 return;
660 }
661
662 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
663
664 g_hash_table_add (self->module_licenses, g_strdup (license));
665 }
666
667
668 void
modulemd_module_stream_v2_replace_module_licenses(ModulemdModuleStreamV2 * self,GHashTable * set)669 modulemd_module_stream_v2_replace_module_licenses (
670 ModulemdModuleStreamV2 *self, GHashTable *set)
671 {
672 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
673
674 MODULEMD_REPLACE_SET (self->module_licenses, set);
675 }
676
677
678 void
modulemd_module_stream_v2_remove_content_license(ModulemdModuleStreamV2 * self,const gchar * license)679 modulemd_module_stream_v2_remove_content_license (ModulemdModuleStreamV2 *self,
680 const gchar *license)
681 {
682 if (!license)
683 {
684 return;
685 }
686
687 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
688
689 g_hash_table_remove (self->content_licenses, license);
690 }
691
692
693 void
modulemd_module_stream_v2_remove_module_license(ModulemdModuleStreamV2 * self,const gchar * license)694 modulemd_module_stream_v2_remove_module_license (ModulemdModuleStreamV2 *self,
695 const gchar *license)
696 {
697 if (!license)
698 {
699 return;
700 }
701
702 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
703
704 g_hash_table_remove (self->module_licenses, license);
705 }
706
707
708 void
modulemd_module_stream_v2_clear_content_licenses(ModulemdModuleStreamV2 * self)709 modulemd_module_stream_v2_clear_content_licenses (ModulemdModuleStreamV2 *self)
710 {
711 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
712
713 g_hash_table_remove_all (self->content_licenses);
714 }
715
716
717 void
modulemd_module_stream_v2_clear_module_licenses(ModulemdModuleStreamV2 * self)718 modulemd_module_stream_v2_clear_module_licenses (ModulemdModuleStreamV2 *self)
719 {
720 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
721
722 g_hash_table_remove_all (self->module_licenses);
723 }
724
725
726 GStrv
modulemd_module_stream_v2_get_content_licenses_as_strv(ModulemdModuleStreamV2 * self)727 modulemd_module_stream_v2_get_content_licenses_as_strv (
728 ModulemdModuleStreamV2 *self)
729 {
730 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
731
732 return modulemd_ordered_str_keys_as_strv (self->content_licenses);
733 }
734
735
736 GStrv
modulemd_module_stream_v2_get_module_licenses_as_strv(ModulemdModuleStreamV2 * self)737 modulemd_module_stream_v2_get_module_licenses_as_strv (
738 ModulemdModuleStreamV2 *self)
739 {
740 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
741
742 return modulemd_ordered_str_keys_as_strv (self->module_licenses);
743 }
744
745
746 void
modulemd_module_stream_v2_add_profile(ModulemdModuleStreamV2 * self,ModulemdProfile * profile)747 modulemd_module_stream_v2_add_profile (ModulemdModuleStreamV2 *self,
748 ModulemdProfile *profile)
749 {
750 if (!profile)
751 {
752 return;
753 }
754 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
755 g_return_if_fail (MODULEMD_IS_PROFILE (profile));
756
757 ModulemdProfile *copied_profile = modulemd_profile_copy (profile);
758 modulemd_profile_set_owner (copied_profile, MODULEMD_MODULE_STREAM (self));
759
760 g_hash_table_replace (self->profiles,
761 g_strdup (modulemd_profile_get_name (profile)),
762 copied_profile);
763 }
764
765
766 void
modulemd_module_stream_v2_clear_profiles(ModulemdModuleStreamV2 * self)767 modulemd_module_stream_v2_clear_profiles (ModulemdModuleStreamV2 *self)
768 {
769 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
770
771 g_hash_table_remove_all (self->profiles);
772 }
773
774
775 GStrv
modulemd_module_stream_v2_get_profile_names_as_strv(ModulemdModuleStreamV2 * self)776 modulemd_module_stream_v2_get_profile_names_as_strv (
777 ModulemdModuleStreamV2 *self)
778 {
779 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
780
781 return modulemd_ordered_str_keys_as_strv (self->profiles);
782 }
783
784
785 ModulemdProfile *
modulemd_module_stream_v2_get_profile(ModulemdModuleStreamV2 * self,const gchar * profile_name)786 modulemd_module_stream_v2_get_profile (ModulemdModuleStreamV2 *self,
787 const gchar *profile_name)
788 {
789 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
790
791 return g_hash_table_lookup (self->profiles, profile_name);
792 }
793
794
795 struct profile_match_ctx
796 {
797 GHashTable *profiles;
798 GPtrArray *found;
799 const gchar *pattern;
800 };
801
802 static void
profile_match(gpointer data,gpointer user_data)803 profile_match (gpointer data, gpointer user_data)
804 {
805 struct profile_match_ctx *match_ctx = (struct profile_match_ctx *)user_data;
806
807 /* Add it to the found list if it matches the pattern */
808 if (modulemd_fnmatch (match_ctx->pattern, (const gchar *)data))
809 {
810 g_ptr_array_add (match_ctx->found,
811 g_object_ref (g_hash_table_lookup (
812 match_ctx->profiles, (const gchar *)data)));
813 }
814 }
815
816 GPtrArray *
modulemd_module_stream_v2_search_profiles(ModulemdModuleStreamV2 * self,const gchar * profile_pattern)817 modulemd_module_stream_v2_search_profiles (ModulemdModuleStreamV2 *self,
818 const gchar *profile_pattern)
819 {
820 /* The list of profiles will probably never be large, so we'll optimize for
821 * the worst-case and preallocate the array to the number of profiles.
822 */
823 GPtrArray *found =
824 g_ptr_array_new_full (g_hash_table_size (self->profiles), g_object_unref);
825
826 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), found);
827
828 g_autoptr (GPtrArray) profile_names =
829 modulemd_ordered_str_keys (self->profiles, modulemd_strcmp_sort);
830
831 struct profile_match_ctx match_ctx = { .profiles = self->profiles,
832 .found = found,
833 .pattern = profile_pattern };
834
835 g_ptr_array_foreach (profile_names, profile_match, &match_ctx);
836
837 return found;
838 }
839
840
841 void
modulemd_module_stream_v2_add_rpm_api(ModulemdModuleStreamV2 * self,const gchar * rpm)842 modulemd_module_stream_v2_add_rpm_api (ModulemdModuleStreamV2 *self,
843 const gchar *rpm)
844 {
845 if (!rpm)
846 {
847 return;
848 }
849
850 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
851
852 g_hash_table_add (self->rpm_api, g_strdup (rpm));
853 }
854
855
856 void
modulemd_module_stream_v2_replace_rpm_api(ModulemdModuleStreamV2 * self,GHashTable * set)857 modulemd_module_stream_v2_replace_rpm_api (ModulemdModuleStreamV2 *self,
858 GHashTable *set)
859 {
860 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
861
862 MODULEMD_REPLACE_SET (self->rpm_api, set);
863 }
864
865
866 void
modulemd_module_stream_v2_remove_rpm_api(ModulemdModuleStreamV2 * self,const gchar * rpm)867 modulemd_module_stream_v2_remove_rpm_api (ModulemdModuleStreamV2 *self,
868 const gchar *rpm)
869 {
870 if (!rpm)
871 {
872 return;
873 }
874
875 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
876
877 g_hash_table_remove (self->rpm_api, rpm);
878 }
879
880
881 void
modulemd_module_stream_v2_clear_rpm_api(ModulemdModuleStreamV2 * self)882 modulemd_module_stream_v2_clear_rpm_api (ModulemdModuleStreamV2 *self)
883 {
884 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
885
886 g_hash_table_remove_all (self->rpm_api);
887 }
888
889
890 GStrv
modulemd_module_stream_v2_get_rpm_api_as_strv(ModulemdModuleStreamV2 * self)891 modulemd_module_stream_v2_get_rpm_api_as_strv (ModulemdModuleStreamV2 *self)
892 {
893 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
894
895 return modulemd_ordered_str_keys_as_strv (self->rpm_api);
896 }
897
898
899 void
modulemd_module_stream_v2_add_rpm_artifact(ModulemdModuleStreamV2 * self,const gchar * nevr)900 modulemd_module_stream_v2_add_rpm_artifact (ModulemdModuleStreamV2 *self,
901 const gchar *nevr)
902 {
903 if (!nevr)
904 {
905 return;
906 }
907
908 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
909
910 g_hash_table_add (self->rpm_artifacts, g_strdup (nevr));
911 }
912
913
914 void
modulemd_module_stream_v2_replace_rpm_artifacts(ModulemdModuleStreamV2 * self,GHashTable * set)915 modulemd_module_stream_v2_replace_rpm_artifacts (ModulemdModuleStreamV2 *self,
916 GHashTable *set)
917 {
918 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
919
920 MODULEMD_REPLACE_SET (self->rpm_artifacts, set);
921 }
922
923
924 void
modulemd_module_stream_v2_remove_rpm_artifact(ModulemdModuleStreamV2 * self,const gchar * nevr)925 modulemd_module_stream_v2_remove_rpm_artifact (ModulemdModuleStreamV2 *self,
926 const gchar *nevr)
927 {
928 if (!nevr)
929 {
930 return;
931 }
932
933 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
934
935 g_hash_table_remove (self->rpm_artifacts, nevr);
936 }
937
938
939 void
modulemd_module_stream_v2_clear_rpm_artifacts(ModulemdModuleStreamV2 * self)940 modulemd_module_stream_v2_clear_rpm_artifacts (ModulemdModuleStreamV2 *self)
941 {
942 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
943
944 g_hash_table_remove_all (self->rpm_artifacts);
945 }
946
947
948 GStrv
modulemd_module_stream_v2_get_rpm_artifacts_as_strv(ModulemdModuleStreamV2 * self)949 modulemd_module_stream_v2_get_rpm_artifacts_as_strv (
950 ModulemdModuleStreamV2 *self)
951 {
952 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
953
954 return modulemd_ordered_str_keys_as_strv (self->rpm_artifacts);
955 }
956
957
958 static GHashTable *
get_or_create_digest_table(ModulemdModuleStreamV2 * self,const gchar * digest)959 get_or_create_digest_table (ModulemdModuleStreamV2 *self, const gchar *digest)
960 {
961 GHashTable *digest_table =
962 g_hash_table_lookup (self->rpm_artifact_map, digest);
963 if (digest_table == NULL)
964 {
965 digest_table = g_hash_table_new_full (
966 g_str_hash, g_str_equal, g_free, g_object_unref);
967 g_hash_table_insert (
968 self->rpm_artifact_map, g_strdup (digest), digest_table);
969 }
970
971 return digest_table;
972 }
973
974
975 void
modulemd_module_stream_v2_set_rpm_artifact_map_entry(ModulemdModuleStreamV2 * self,ModulemdRpmMapEntry * entry,const gchar * digest,const gchar * checksum)976 modulemd_module_stream_v2_set_rpm_artifact_map_entry (
977 ModulemdModuleStreamV2 *self,
978 ModulemdRpmMapEntry *entry,
979 const gchar *digest,
980 const gchar *checksum)
981 {
982 GHashTable *digest_table = NULL;
983
984 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
985 g_return_if_fail (entry && digest && checksum);
986
987 digest_table = get_or_create_digest_table (self, digest);
988
989 g_hash_table_insert (
990 digest_table, g_strdup (checksum), modulemd_rpm_map_entry_copy (entry));
991 }
992
993
994 ModulemdRpmMapEntry *
modulemd_module_stream_v2_get_rpm_artifact_map_entry(ModulemdModuleStreamV2 * self,const gchar * digest,const gchar * checksum)995 modulemd_module_stream_v2_get_rpm_artifact_map_entry (
996 ModulemdModuleStreamV2 *self, const gchar *digest, const gchar *checksum)
997 {
998 GHashTable *digest_table = NULL;
999 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
1000 g_return_val_if_fail (digest && checksum, NULL);
1001
1002 digest_table = g_hash_table_lookup (self->rpm_artifact_map, digest);
1003 if (!digest_table)
1004 {
1005 return NULL;
1006 }
1007
1008 return g_hash_table_lookup (digest_table, checksum);
1009 }
1010
1011
1012 void
modulemd_module_stream_v2_add_rpm_filter(ModulemdModuleStreamV2 * self,const gchar * rpm)1013 modulemd_module_stream_v2_add_rpm_filter (ModulemdModuleStreamV2 *self,
1014 const gchar *rpm)
1015 {
1016 if (!rpm)
1017 {
1018 return;
1019 }
1020
1021 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
1022
1023 g_hash_table_add (self->rpm_filters, g_strdup (rpm));
1024 }
1025
1026
1027 void
modulemd_module_stream_v2_replace_rpm_filters(ModulemdModuleStreamV2 * self,GHashTable * set)1028 modulemd_module_stream_v2_replace_rpm_filters (ModulemdModuleStreamV2 *self,
1029 GHashTable *set)
1030 {
1031 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
1032
1033 MODULEMD_REPLACE_SET (self->rpm_filters, set);
1034 }
1035
1036
1037 void
modulemd_module_stream_v2_remove_rpm_filter(ModulemdModuleStreamV2 * self,const gchar * rpm)1038 modulemd_module_stream_v2_remove_rpm_filter (ModulemdModuleStreamV2 *self,
1039 const gchar *rpm)
1040 {
1041 if (!rpm)
1042 {
1043 return;
1044 }
1045
1046 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
1047
1048 g_hash_table_remove (self->rpm_filters, rpm);
1049 }
1050
1051
1052 void
modulemd_module_stream_v2_clear_rpm_filters(ModulemdModuleStreamV2 * self)1053 modulemd_module_stream_v2_clear_rpm_filters (ModulemdModuleStreamV2 *self)
1054 {
1055 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
1056
1057 g_hash_table_remove_all (self->rpm_filters);
1058 }
1059
1060
1061 GStrv
modulemd_module_stream_v2_get_rpm_filters_as_strv(ModulemdModuleStreamV2 * self)1062 modulemd_module_stream_v2_get_rpm_filters_as_strv (
1063 ModulemdModuleStreamV2 *self)
1064 {
1065 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
1066
1067 return modulemd_ordered_str_keys_as_strv (self->rpm_filters);
1068 }
1069
1070
1071 void
modulemd_module_stream_v2_add_demodularized_rpm(ModulemdModuleStreamV2 * self,const gchar * rpm)1072 modulemd_module_stream_v2_add_demodularized_rpm (ModulemdModuleStreamV2 *self,
1073 const gchar *rpm)
1074 {
1075 if (!rpm)
1076 {
1077 return;
1078 }
1079
1080 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
1081
1082 g_hash_table_add (self->demodularized_rpms, g_strdup (rpm));
1083 }
1084
1085
1086 void
modulemd_module_stream_v2_replace_demodularized_rpms(ModulemdModuleStreamV2 * self,GHashTable * set)1087 modulemd_module_stream_v2_replace_demodularized_rpms (
1088 ModulemdModuleStreamV2 *self, GHashTable *set)
1089 {
1090 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
1091
1092 MODULEMD_REPLACE_SET (self->demodularized_rpms, set);
1093 }
1094
1095
1096 void
modulemd_module_stream_v2_remove_demodularized_rpm(ModulemdModuleStreamV2 * self,const gchar * rpm)1097 modulemd_module_stream_v2_remove_demodularized_rpm (
1098 ModulemdModuleStreamV2 *self, const gchar *rpm)
1099 {
1100 if (!rpm)
1101 {
1102 return;
1103 }
1104
1105 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
1106
1107 g_hash_table_remove (self->demodularized_rpms, rpm);
1108 }
1109
1110
1111 void
modulemd_module_stream_v2_clear_demodularized_rpms(ModulemdModuleStreamV2 * self)1112 modulemd_module_stream_v2_clear_demodularized_rpms (
1113 ModulemdModuleStreamV2 *self)
1114 {
1115 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
1116
1117 g_hash_table_remove_all (self->demodularized_rpms);
1118 }
1119
1120
1121 GStrv
modulemd_module_stream_v2_get_demodularized_rpms(ModulemdModuleStreamV2 * self)1122 modulemd_module_stream_v2_get_demodularized_rpms (ModulemdModuleStreamV2 *self)
1123 {
1124 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
1125
1126 return modulemd_ordered_str_keys_as_strv (self->demodularized_rpms);
1127 }
1128
1129
1130 void
modulemd_module_stream_v2_add_servicelevel(ModulemdModuleStreamV2 * self,ModulemdServiceLevel * servicelevel)1131 modulemd_module_stream_v2_add_servicelevel (ModulemdModuleStreamV2 *self,
1132 ModulemdServiceLevel *servicelevel)
1133 {
1134 if (!servicelevel)
1135 {
1136 return;
1137 }
1138 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
1139 g_return_if_fail (MODULEMD_IS_SERVICE_LEVEL (servicelevel));
1140
1141 g_hash_table_replace (
1142 self->servicelevels,
1143 g_strdup (modulemd_service_level_get_name (servicelevel)),
1144 modulemd_service_level_copy (servicelevel));
1145 }
1146
1147
1148 void
modulemd_module_stream_v2_clear_servicelevels(ModulemdModuleStreamV2 * self)1149 modulemd_module_stream_v2_clear_servicelevels (ModulemdModuleStreamV2 *self)
1150 {
1151 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
1152
1153 g_hash_table_remove_all (self->servicelevels);
1154 }
1155
1156
1157 GStrv
modulemd_module_stream_v2_get_servicelevel_names_as_strv(ModulemdModuleStreamV2 * self)1158 modulemd_module_stream_v2_get_servicelevel_names_as_strv (
1159 ModulemdModuleStreamV2 *self)
1160 {
1161 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
1162
1163 return modulemd_ordered_str_keys_as_strv (self->servicelevels);
1164 }
1165
1166
1167 ModulemdServiceLevel *
modulemd_module_stream_v2_get_servicelevel(ModulemdModuleStreamV2 * self,const gchar * servicelevel_name)1168 modulemd_module_stream_v2_get_servicelevel (ModulemdModuleStreamV2 *self,
1169 const gchar *servicelevel_name)
1170 {
1171 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
1172
1173 return g_hash_table_lookup (self->servicelevels, servicelevel_name);
1174 }
1175
1176
1177 void
modulemd_module_stream_v2_add_dependencies(ModulemdModuleStreamV2 * self,ModulemdDependencies * deps)1178 modulemd_module_stream_v2_add_dependencies (ModulemdModuleStreamV2 *self,
1179 ModulemdDependencies *deps)
1180 {
1181 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
1182
1183 g_ptr_array_add (self->dependencies, modulemd_dependencies_copy (deps));
1184 }
1185
1186
1187 void
modulemd_module_stream_v2_replace_dependencies(ModulemdModuleStreamV2 * self,GPtrArray * array)1188 modulemd_module_stream_v2_replace_dependencies (ModulemdModuleStreamV2 *self,
1189 GPtrArray *array)
1190 {
1191 gsize i;
1192 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
1193
1194 for (i = 0; i < array->len; i++)
1195 {
1196 modulemd_module_stream_v2_add_dependencies (
1197 self, g_ptr_array_index (array, i));
1198 }
1199 }
1200
1201
1202 void
modulemd_module_stream_v2_clear_dependencies(ModulemdModuleStreamV2 * self)1203 modulemd_module_stream_v2_clear_dependencies (ModulemdModuleStreamV2 *self)
1204 {
1205 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
1206
1207 g_ptr_array_set_size (self->dependencies, 0);
1208 }
1209
1210
1211 static gboolean
dep_equal_wrapper(gconstpointer a,gconstpointer b)1212 dep_equal_wrapper (gconstpointer a, gconstpointer b)
1213 {
1214 return modulemd_dependencies_equals ((ModulemdDependencies *)a,
1215 (ModulemdDependencies *)b);
1216 }
1217
1218
1219 void
modulemd_module_stream_v2_remove_dependencies(ModulemdModuleStreamV2 * self,ModulemdDependencies * deps)1220 modulemd_module_stream_v2_remove_dependencies (ModulemdModuleStreamV2 *self,
1221 ModulemdDependencies *deps)
1222 {
1223 guint index;
1224 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
1225
1226 while (g_ptr_array_find_with_equal_func (
1227 self->dependencies, deps, dep_equal_wrapper, &index))
1228 {
1229 g_ptr_array_remove_index (self->dependencies, index);
1230 }
1231 }
1232
1233
1234 GPtrArray *
modulemd_module_stream_v2_get_dependencies(ModulemdModuleStreamV2 * self)1235 modulemd_module_stream_v2_get_dependencies (ModulemdModuleStreamV2 *self)
1236 {
1237 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
1238
1239 return self->dependencies;
1240 }
1241
1242
1243 void
modulemd_module_stream_v2_set_xmd(ModulemdModuleStreamV2 * self,GVariant * xmd)1244 modulemd_module_stream_v2_set_xmd (ModulemdModuleStreamV2 *self, GVariant *xmd)
1245 {
1246 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self));
1247
1248 /* Do nothing if we were passed the same pointer */
1249 if (self->xmd == xmd)
1250 {
1251 return;
1252 }
1253
1254 g_clear_pointer (&self->xmd, g_variant_unref);
1255 self->xmd = modulemd_variant_deep_copy (xmd);
1256 }
1257
1258 GVariant *
modulemd_module_stream_v2_get_xmd(ModulemdModuleStreamV2 * self)1259 modulemd_module_stream_v2_get_xmd (ModulemdModuleStreamV2 *self)
1260 {
1261 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
1262 return self->xmd;
1263 }
1264
1265
1266 gboolean
modulemd_module_stream_v2_includes_nevra(ModulemdModuleStreamV2 * self,const gchar * nevra_pattern)1267 modulemd_module_stream_v2_includes_nevra (ModulemdModuleStreamV2 *self,
1268 const gchar *nevra_pattern)
1269 {
1270 /* If g_hash_table_find() returns non-NULL, the nevra was found in this
1271 * module stream, so return TRUE
1272 */
1273 return !!g_hash_table_find (
1274 self->rpm_artifacts, modulemd_rpm_match, (void *)nevra_pattern);
1275 }
1276
1277
1278 void
modulemd_module_stream_v2_set_static_context(ModulemdModuleStreamV2 * self)1279 modulemd_module_stream_v2_set_static_context (ModulemdModuleStreamV2 *self)
1280 {
1281 self->static_context = TRUE;
1282
1283 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATIC_CONTEXT]);
1284 }
1285
1286
1287 void
modulemd_module_stream_v2_unset_static_context(ModulemdModuleStreamV2 * self)1288 modulemd_module_stream_v2_unset_static_context (ModulemdModuleStreamV2 *self)
1289 {
1290 self->static_context = FALSE;
1291
1292 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATIC_CONTEXT]);
1293 }
1294
1295
1296 gboolean
modulemd_module_stream_v2_is_static_context(ModulemdModuleStreamV2 * self)1297 modulemd_module_stream_v2_is_static_context (ModulemdModuleStreamV2 *self)
1298 {
1299 return self->static_context;
1300 }
1301
1302
1303 static gboolean
modulemd_module_stream_v2_validate_context(const gchar * context,GError ** error)1304 modulemd_module_stream_v2_validate_context (const gchar *context,
1305 GError **error)
1306 {
1307 /* must be string of up to MODULEMD_MODULE_STREAM_V2_MAXCONTEXTLEN [a-zA-Z0-9_] */
1308
1309 if (context == NULL || *context == '\0')
1310 {
1311 g_set_error (
1312 error, MODULEMD_ERROR, MMD_ERROR_VALIDATE, "Empty stream context");
1313 return FALSE;
1314 }
1315
1316 if (strlen (context) > MODULEMD_MODULE_STREAM_V2_MAXCONTEXTLEN)
1317 {
1318 g_set_error (error,
1319 MODULEMD_ERROR,
1320 MMD_ERROR_VALIDATE,
1321 "Stream context '%s' exceeds maximum length (%d)",
1322 context,
1323 MODULEMD_MODULE_STREAM_V2_MAXCONTEXTLEN);
1324 return FALSE;
1325 }
1326
1327 for (const gchar *i = context; *i != '\0'; i++)
1328 {
1329 if (!g_ascii_isalnum (*i) && *i != '_')
1330 {
1331 g_set_error (
1332 error,
1333 MODULEMD_ERROR,
1334 MMD_ERROR_VALIDATE,
1335 "Stream context '%s' can only contain [a-zA-Z0-9_] characters",
1336 context);
1337 return FALSE;
1338 }
1339 }
1340
1341 return TRUE;
1342 }
1343
1344
1345 static gboolean
modulemd_module_stream_v2_validate(ModulemdModuleStream * self,GError ** error)1346 modulemd_module_stream_v2_validate (ModulemdModuleStream *self, GError **error)
1347 {
1348 GHashTableIter iter;
1349 gpointer key;
1350 gpointer value;
1351 gchar *nevra = NULL;
1352 ModulemdModuleStreamV2 *v2_self = NULL;
1353 ModulemdDependencies *deps = NULL;
1354 g_autoptr (GError) nested_error = NULL;
1355 g_auto (GStrv) buildopts_arches = NULL;
1356 const gchar *context = NULL;
1357
1358 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), FALSE);
1359 v2_self = MODULEMD_MODULE_STREAM_V2 (self);
1360
1361 if (!MODULEMD_MODULE_STREAM_CLASS (modulemd_module_stream_v2_parent_class)
1362 ->validate (self, error))
1363 {
1364 return FALSE;
1365 }
1366
1367 /* Validate static context if present */
1368 if (v2_self->static_context)
1369 {
1370 context =
1371 modulemd_module_stream_get_context (MODULEMD_MODULE_STREAM (self));
1372 if (context)
1373 {
1374 if (!modulemd_module_stream_v2_validate_context (context,
1375 &nested_error))
1376 {
1377 g_propagate_error (error, g_steal_pointer (&nested_error));
1378 return FALSE;
1379 }
1380 }
1381 }
1382
1383 /* Make sure that mandatory fields are present */
1384 if (!modulemd_module_stream_v2_get_summary (v2_self, "C"))
1385 {
1386 g_set_error (error,
1387 MODULEMD_YAML_ERROR,
1388 MMD_YAML_ERROR_MISSING_REQUIRED,
1389 "Summary is missing");
1390 return FALSE;
1391 }
1392
1393 if (!modulemd_module_stream_v2_get_description (v2_self, "C"))
1394 {
1395 g_set_error (error,
1396 MODULEMD_YAML_ERROR,
1397 MMD_YAML_ERROR_MISSING_REQUIRED,
1398 "Description is missing");
1399 return FALSE;
1400 }
1401
1402 if (!g_hash_table_size (v2_self->module_licenses))
1403 {
1404 g_set_error (error,
1405 MODULEMD_YAML_ERROR,
1406 MMD_YAML_ERROR_MISSING_REQUIRED,
1407 "Module license is missing");
1408 return FALSE;
1409 }
1410
1411 /* Verify that the components are consistent with regards to buildorder and
1412 * buildafter values.
1413 */
1414 if (!modulemd_module_stream_validate_components (v2_self->rpm_components,
1415 &nested_error))
1416 {
1417 g_propagate_error (error, g_steal_pointer (&nested_error));
1418 return FALSE;
1419 }
1420
1421 if (v2_self->buildopts != NULL)
1422 {
1423 /* Verify that the component rpm arches are consistent with any module
1424 * level arches.
1425 */
1426 buildopts_arches =
1427 modulemd_buildopts_get_arches_as_strv (v2_self->buildopts);
1428 if (!modulemd_module_stream_validate_component_rpm_arches (
1429 v2_self->rpm_components, buildopts_arches, &nested_error))
1430 {
1431 g_propagate_error (error, g_steal_pointer (&nested_error));
1432 return FALSE;
1433 }
1434 }
1435
1436 /* Iterate through the artifacts and validate that they are in the proper
1437 * NEVRA format
1438 */
1439 g_hash_table_iter_init (&iter, v2_self->rpm_artifacts);
1440 while (g_hash_table_iter_next (&iter, &key, &value))
1441 {
1442 nevra = (gchar *)key;
1443 if (!modulemd_validate_nevra (nevra))
1444 {
1445 g_set_error (error,
1446 MODULEMD_ERROR,
1447 MMD_ERROR_VALIDATE,
1448 "Artifact '%s' was not in valid N-E:V-R.A format.",
1449 nevra);
1450 return FALSE;
1451 }
1452 }
1453
1454 /* Iterate through the Dependencies and validate them */
1455 for (guint i = 0; i < v2_self->dependencies->len; i++)
1456 {
1457 deps =
1458 MODULEMD_DEPENDENCIES (g_ptr_array_index (v2_self->dependencies, i));
1459 if (!modulemd_dependencies_validate (deps, &nested_error))
1460 {
1461 g_propagate_prefixed_error (error,
1462 g_steal_pointer (&nested_error),
1463 "Dependency failed to validate: ");
1464 return FALSE;
1465 }
1466 }
1467
1468 return TRUE;
1469 }
1470
1471
1472 static void
modulemd_module_stream_v2_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1473 modulemd_module_stream_v2_get_property (GObject *object,
1474 guint prop_id,
1475 GValue *value,
1476 GParamSpec *pspec)
1477 {
1478 ModulemdModuleStreamV2 *self = MODULEMD_MODULE_STREAM_V2 (object);
1479
1480 switch (prop_id)
1481 {
1482 case PROP_ARCH:
1483 g_value_set_string (value, modulemd_module_stream_v2_get_arch (self));
1484 break;
1485
1486 case PROP_BUILDOPTS:
1487 g_value_set_object (value,
1488 modulemd_module_stream_v2_get_buildopts (self));
1489 break;
1490
1491 case PROP_COMMUNITY:
1492 g_value_set_string (value,
1493 modulemd_module_stream_v2_get_community (self));
1494 break;
1495
1496 case PROP_DOCUMENTATION:
1497 g_value_set_string (value,
1498 modulemd_module_stream_v2_get_documentation (self));
1499 break;
1500
1501 case PROP_TRACKER:
1502 g_value_set_string (value, modulemd_module_stream_v2_get_tracker (self));
1503 break;
1504
1505 case PROP_STATIC_CONTEXT:
1506 g_value_set_boolean (value,
1507 modulemd_module_stream_v2_is_static_context (self));
1508 break;
1509
1510 default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1511 }
1512 }
1513
1514 static void
modulemd_module_stream_v2_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1515 modulemd_module_stream_v2_set_property (GObject *object,
1516 guint prop_id,
1517 const GValue *value,
1518 GParamSpec *pspec)
1519 {
1520 ModulemdModuleStreamV2 *self = MODULEMD_MODULE_STREAM_V2 (object);
1521 switch (prop_id)
1522 {
1523 case PROP_ARCH:
1524 modulemd_module_stream_v2_set_arch (self, g_value_get_string (value));
1525 break;
1526
1527 case PROP_BUILDOPTS:
1528 modulemd_module_stream_v2_set_buildopts (self,
1529 g_value_get_object (value));
1530 break;
1531
1532 case PROP_COMMUNITY:
1533 modulemd_module_stream_v2_set_community (self,
1534 g_value_get_string (value));
1535 break;
1536
1537 case PROP_DOCUMENTATION:
1538 modulemd_module_stream_v2_set_documentation (self,
1539 g_value_get_string (value));
1540 break;
1541
1542 case PROP_TRACKER:
1543 modulemd_module_stream_v2_set_tracker (self, g_value_get_string (value));
1544 break;
1545
1546 case PROP_STATIC_CONTEXT:
1547 if (g_value_get_boolean (value))
1548 {
1549 modulemd_module_stream_v2_set_static_context (self);
1550 }
1551 else
1552 {
1553 modulemd_module_stream_v2_unset_static_context (self);
1554 }
1555 break;
1556
1557 default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1558 }
1559 }
1560
1561 static void
copy_rpm_artifact_map(ModulemdModuleStreamV2 * from,ModulemdModuleStreamV2 * to)1562 copy_rpm_artifact_map (ModulemdModuleStreamV2 *from,
1563 ModulemdModuleStreamV2 *to)
1564 {
1565 GHashTableIter outer;
1566 GHashTableIter inner;
1567 gpointer outer_key;
1568 gpointer outer_value;
1569 gpointer inner_key;
1570 gpointer inner_value;
1571 GHashTable *to_digest_table = NULL;
1572
1573 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (from));
1574 g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (to));
1575
1576 g_hash_table_iter_init (&outer, from->rpm_artifact_map);
1577 while (g_hash_table_iter_next (&outer, &outer_key, &outer_value))
1578 {
1579 to_digest_table = get_or_create_digest_table (to, outer_key);
1580
1581 g_hash_table_iter_init (&inner, (GHashTable *)outer_value);
1582 while (g_hash_table_iter_next (&inner, &inner_key, &inner_value))
1583 {
1584 g_hash_table_insert (to_digest_table,
1585 g_strdup (inner_key),
1586 modulemd_rpm_map_entry_copy (inner_value));
1587 }
1588 }
1589 }
1590
1591 static ModulemdModuleStream *
modulemd_module_stream_v2_copy(ModulemdModuleStream * self,const gchar * module_name,const gchar * module_stream)1592 modulemd_module_stream_v2_copy (ModulemdModuleStream *self,
1593 const gchar *module_name,
1594 const gchar *module_stream)
1595 {
1596 ModulemdModuleStreamV2 *v2_self = NULL;
1597 g_autoptr (ModulemdModuleStreamV2) copy = NULL;
1598 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), NULL);
1599 v2_self = MODULEMD_MODULE_STREAM_V2 (self);
1600
1601 copy = MODULEMD_MODULE_STREAM_V2 (
1602 MODULEMD_MODULE_STREAM_CLASS (modulemd_module_stream_v2_parent_class)
1603 ->copy (self, module_name, module_stream));
1604
1605 /* Properties */
1606 STREAM_COPY_IF_SET (v2, copy, v2_self, arch);
1607 STREAM_COPY_IF_SET (v2, copy, v2_self, buildopts);
1608 STREAM_COPY_IF_SET (v2, copy, v2_self, community);
1609 STREAM_COPY_IF_SET_WITH_LOCALE (v2, copy, v2_self, description);
1610 STREAM_COPY_IF_SET (v2, copy, v2_self, documentation);
1611 STREAM_COPY_IF_SET_WITH_LOCALE (v2, copy, v2_self, summary);
1612 STREAM_COPY_IF_SET (v2, copy, v2_self, tracker);
1613 copy->static_context = v2_self->static_context;
1614
1615 /* Internal Data Structures: With replace function */
1616 STREAM_REPLACE_HASHTABLE (v2, copy, v2_self, content_licenses);
1617 STREAM_REPLACE_HASHTABLE (v2, copy, v2_self, module_licenses);
1618 STREAM_REPLACE_HASHTABLE (v2, copy, v2_self, rpm_api);
1619 STREAM_REPLACE_HASHTABLE (v2, copy, v2_self, rpm_artifacts);
1620 STREAM_REPLACE_HASHTABLE (v2, copy, v2_self, rpm_filters);
1621 STREAM_REPLACE_HASHTABLE (v2, copy, v2_self, demodularized_rpms);
1622
1623 /* Internal Data Structures: With add on value */
1624 COPY_HASHTABLE_BY_VALUE_ADDER (
1625 copy, v2_self, rpm_components, modulemd_module_stream_v2_add_component);
1626 COPY_HASHTABLE_BY_VALUE_ADDER (
1627 copy, v2_self, module_components, modulemd_module_stream_v2_add_component);
1628 COPY_HASHTABLE_BY_VALUE_ADDER (
1629 copy, v2_self, profiles, modulemd_module_stream_v2_add_profile);
1630 COPY_HASHTABLE_BY_VALUE_ADDER (
1631 copy, v2_self, servicelevels, modulemd_module_stream_v2_add_servicelevel);
1632
1633 STREAM_REPLACE_HASHTABLE (v2, copy, v2_self, dependencies);
1634
1635 copy_rpm_artifact_map (v2_self, copy);
1636
1637 STREAM_COPY_IF_SET (v2, copy, v2_self, xmd);
1638
1639 modulemd_module_stream_v2_associate_obsoletes (
1640 copy, modulemd_module_stream_v2_get_obsoletes (v2_self));
1641
1642 return MODULEMD_MODULE_STREAM (g_steal_pointer (©));
1643 }
1644
1645
1646 static gboolean
depends_on_stream(ModulemdModuleStreamV2 * self,const gchar * module_name,const gchar * stream_name,gboolean is_builddep)1647 depends_on_stream (ModulemdModuleStreamV2 *self,
1648 const gchar *module_name,
1649 const gchar *stream_name,
1650 gboolean is_builddep)
1651 {
1652 ModulemdDependencies *dep = NULL;
1653
1654 /* Iterate through all of the dependency objects */
1655 for (gint i = 0; i < self->dependencies->len; i++)
1656 {
1657 dep = g_ptr_array_index (self->dependencies, i);
1658 if (is_builddep)
1659 {
1660 if (modulemd_dependencies_buildrequires_module_and_stream (
1661 dep, module_name, stream_name))
1662 {
1663 return TRUE;
1664 }
1665 }
1666 else
1667 {
1668 if (modulemd_dependencies_requires_module_and_stream (
1669 dep, module_name, stream_name))
1670 {
1671 return TRUE;
1672 }
1673 }
1674 }
1675
1676 return FALSE;
1677 }
1678
1679 static gboolean
modulemd_module_stream_v2_depends_on_stream(ModulemdModuleStream * self,const gchar * module_name,const gchar * stream_name)1680 modulemd_module_stream_v2_depends_on_stream (ModulemdModuleStream *self,
1681 const gchar *module_name,
1682 const gchar *stream_name)
1683 {
1684 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), FALSE);
1685 g_return_val_if_fail (module_name && stream_name, FALSE);
1686
1687 return depends_on_stream (
1688 MODULEMD_MODULE_STREAM_V2 (self), module_name, stream_name, FALSE);
1689 }
1690
1691
1692 static gboolean
modulemd_module_stream_v2_build_depends_on_stream(ModulemdModuleStream * self,const gchar * module_name,const gchar * stream_name)1693 modulemd_module_stream_v2_build_depends_on_stream (ModulemdModuleStream *self,
1694 const gchar *module_name,
1695 const gchar *stream_name)
1696 {
1697 g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), FALSE);
1698 g_return_val_if_fail (module_name && stream_name, FALSE);
1699
1700 return depends_on_stream (
1701 MODULEMD_MODULE_STREAM_V2 (self), module_name, stream_name, TRUE);
1702 }
1703
1704
1705 static void
modulemd_module_stream_v2_class_init(ModulemdModuleStreamV2Class * klass)1706 modulemd_module_stream_v2_class_init (ModulemdModuleStreamV2Class *klass)
1707 {
1708 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1709 ModulemdModuleStreamClass *stream_class =
1710 MODULEMD_MODULE_STREAM_CLASS (object_class);
1711
1712 object_class->finalize = modulemd_module_stream_v2_finalize;
1713 object_class->get_property = modulemd_module_stream_v2_get_property;
1714 object_class->set_property = modulemd_module_stream_v2_set_property;
1715
1716 stream_class->get_mdversion = modulemd_module_stream_v2_get_mdversion;
1717 stream_class->copy = modulemd_module_stream_v2_copy;
1718 stream_class->equals = modulemd_module_stream_v2_equals;
1719 stream_class->validate = modulemd_module_stream_v2_validate;
1720 stream_class->depends_on_stream =
1721 modulemd_module_stream_v2_depends_on_stream;
1722 stream_class->build_depends_on_stream =
1723 modulemd_module_stream_v2_build_depends_on_stream;
1724
1725
1726 properties[PROP_ARCH] = g_param_spec_string (
1727 "arch",
1728 "Module Artifact Architecture",
1729 "The architecture of the produced artifacts",
1730 NULL,
1731 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
1732
1733 properties[PROP_BUILDOPTS] =
1734 g_param_spec_object ("buildopts",
1735 "Module Build Options",
1736 "Build options for module components",
1737 MODULEMD_TYPE_BUILDOPTS,
1738 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1739
1740 properties[PROP_COMMUNITY] = g_param_spec_string (
1741 "community",
1742 "Module Community Website",
1743 "The website address of the upstream community for this module",
1744 NULL,
1745 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
1746
1747 properties[PROP_DOCUMENTATION] = g_param_spec_string (
1748 "documentation",
1749 "Module Documentation Website",
1750 "The website address of the upstream documentation for this module",
1751 NULL,
1752 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
1753
1754 properties[PROP_TRACKER] = g_param_spec_string (
1755 "tracker",
1756 "Module Bug Tracker Website",
1757 "The website address of the upstream bug tracker for this module",
1758 NULL,
1759 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
1760
1761 properties[PROP_STATIC_CONTEXT] =
1762 g_param_spec_boolean ("static-context",
1763 "Static Context",
1764 "Whether the context is static",
1765 0,
1766 G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
1767
1768 g_object_class_install_properties (object_class, N_PROPS, properties);
1769 }
1770
1771 static void
modulemd_module_stream_v2_init(ModulemdModuleStreamV2 * self)1772 modulemd_module_stream_v2_init (ModulemdModuleStreamV2 *self)
1773 {
1774 /* Properties */
1775
1776 /* Internal Data Structures */
1777 self->module_components =
1778 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
1779 self->rpm_components =
1780 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
1781
1782
1783 self->content_licenses =
1784 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1785 self->module_licenses =
1786 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1787
1788 self->profiles =
1789 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
1790
1791 self->rpm_api =
1792 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1793
1794 self->rpm_artifacts =
1795 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1796
1797 self->rpm_artifact_map = g_hash_table_new_full (
1798 g_str_hash, g_str_equal, g_free, modulemd_hash_table_unref);
1799
1800 self->rpm_filters =
1801 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1802
1803 self->demodularized_rpms =
1804 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1805
1806 self->servicelevels =
1807 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
1808
1809 /* The common case is for a single entry, so we'll optimize for that when
1810 * preallocating
1811 */
1812 self->dependencies = g_ptr_array_new_full (1, g_object_unref);
1813 }
1814
1815
1816 static gboolean
1817 modulemd_module_stream_v2_parse_licenses (yaml_parser_t *parser,
1818 ModulemdModuleStreamV2 *modulestream,
1819 gboolean strict,
1820 gboolean only_packager,
1821 GError **error);
1822
1823 static gboolean
1824 modulemd_module_stream_v2_parse_servicelevels (
1825 yaml_parser_t *parser,
1826 ModulemdModuleStreamV2 *modulestream,
1827 gboolean strict,
1828 GError **error);
1829
1830 static gboolean
1831 modulemd_module_stream_v2_parse_deps (yaml_parser_t *parser,
1832 ModulemdModuleStreamV2 *modulestream,
1833 gboolean strict,
1834 GError **error);
1835
1836 static gboolean
1837 modulemd_module_stream_v2_parse_refs (yaml_parser_t *parser,
1838 ModulemdModuleStreamV2 *modulestream,
1839 gboolean strict,
1840 GError **error);
1841
1842 static gboolean
1843 modulemd_module_stream_v2_parse_profiles (yaml_parser_t *parser,
1844 ModulemdModuleStreamV2 *modulestream,
1845 gboolean strict,
1846 GError **error);
1847
1848 static gboolean
1849 modulemd_module_stream_v2_parse_components (
1850 yaml_parser_t *parser,
1851 ModulemdModuleStreamV2 *modulestream,
1852 gboolean strict,
1853 GError **error);
1854
1855 static gboolean
1856 modulemd_module_stream_v2_parse_artifacts (
1857 yaml_parser_t *parser,
1858 ModulemdModuleStreamV2 *modulestream,
1859 gboolean strict,
1860 GError **error);
1861
1862
1863 ModulemdModuleStreamV2 *
modulemd_module_stream_v2_parse_yaml(ModulemdSubdocumentInfo * subdoc,gboolean strict,gboolean only_packager,GError ** error)1864 modulemd_module_stream_v2_parse_yaml (ModulemdSubdocumentInfo *subdoc,
1865 gboolean strict,
1866 gboolean only_packager,
1867 GError **error)
1868 {
1869 MODULEMD_INIT_TRACE ();
1870 MMD_INIT_YAML_PARSER (parser);
1871 MMD_INIT_YAML_EVENT (event);
1872 gboolean done = FALSE;
1873 g_autoptr (GError) nested_error = NULL;
1874 g_autoptr (ModulemdModuleStreamV2) modulestream = NULL;
1875 g_autoptr (GHashTable) set = NULL;
1876 g_autoptr (ModulemdBuildopts) buildopts = NULL;
1877 g_autoptr (GVariant) xmd = NULL;
1878 guint64 version;
1879 gboolean static_context;
1880
1881 if (!modulemd_subdocument_info_get_data_parser (
1882 subdoc, &parser, strict, error))
1883 {
1884 return FALSE;
1885 }
1886
1887 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1888
1889 modulestream = modulemd_module_stream_v2_new (NULL, NULL);
1890
1891 /* Read the MAPPING_START */
1892 YAML_PARSER_PARSE_WITH_EXIT (&parser, &event, error);
1893 if (event.type != YAML_MAPPING_START_EVENT)
1894 {
1895 MMD_YAML_ERROR_EVENT_EXIT (
1896 error, event, "Data section did not begin with a map.");
1897 }
1898
1899 /* Process through the mapping */
1900 while (!done)
1901 {
1902 YAML_PARSER_PARSE_WITH_EXIT (&parser, &event, error);
1903
1904 switch (event.type)
1905 {
1906 case YAML_MAPPING_END_EVENT: done = TRUE; break;
1907
1908 case YAML_SCALAR_EVENT:
1909 /* Mapping Keys */
1910
1911 /* Module Name */
1912 if (g_str_equal ((const gchar *)event.data.scalar.value, "name") &&
1913 !only_packager)
1914 {
1915 MMD_SET_PARSED_YAML_STRING (
1916 &parser,
1917 error,
1918 modulemd_module_stream_set_module_name,
1919 MODULEMD_MODULE_STREAM (modulestream));
1920 }
1921
1922 /* Module Stream Name */
1923 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1924 "stream") &&
1925 !only_packager)
1926 {
1927 MMD_SET_PARSED_YAML_STRING (
1928 &parser,
1929 error,
1930 modulemd_module_stream_set_stream_name,
1931 MODULEMD_MODULE_STREAM (modulestream));
1932 }
1933
1934 /* Module Version */
1935 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1936 "version") &&
1937 !only_packager)
1938 {
1939 version = modulemd_yaml_parse_uint64 (&parser, &nested_error);
1940 if (nested_error)
1941 {
1942 g_propagate_error (error, g_steal_pointer (&nested_error));
1943 return NULL;
1944 }
1945
1946 modulemd_module_stream_set_version (
1947 MODULEMD_MODULE_STREAM (modulestream), version);
1948 }
1949
1950 /* Module Context */
1951 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1952 "context") &&
1953 !only_packager)
1954 {
1955 MMD_SET_PARSED_YAML_STRING (
1956 &parser,
1957 error,
1958 modulemd_module_stream_set_context,
1959 MODULEMD_MODULE_STREAM (modulestream));
1960 }
1961
1962 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1963 "static_context"))
1964 {
1965 static_context =
1966 modulemd_yaml_parse_bool (&parser, &nested_error);
1967 if (nested_error)
1968 {
1969 g_propagate_error (error, g_steal_pointer (&nested_error));
1970 return NULL;
1971 }
1972
1973 if (static_context)
1974 {
1975 modulemd_module_stream_v2_set_static_context (modulestream);
1976 }
1977 else
1978 {
1979 modulemd_module_stream_v2_unset_static_context (
1980 modulestream);
1981 }
1982 }
1983
1984 /* Module Artifact Architecture */
1985 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1986 "arch") &&
1987 !only_packager)
1988 {
1989 MMD_SET_PARSED_YAML_STRING (&parser,
1990 error,
1991 modulemd_module_stream_v2_set_arch,
1992 modulestream);
1993 }
1994
1995 /* Module Summary */
1996 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1997 "summary"))
1998 {
1999 MMD_SET_PARSED_YAML_STRING (
2000 &parser,
2001 error,
2002 modulemd_module_stream_v2_set_summary,
2003 modulestream);
2004 }
2005
2006 /* Module Description */
2007 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2008 "description"))
2009 {
2010 MMD_SET_PARSED_YAML_STRING (
2011 &parser,
2012 error,
2013 modulemd_module_stream_v2_set_description,
2014 modulestream);
2015 }
2016
2017 /* Service Levels */
2018 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2019 "servicelevels") &&
2020 !only_packager)
2021 {
2022 if (!modulemd_module_stream_v2_parse_servicelevels (
2023 &parser, modulestream, strict, &nested_error))
2024 {
2025 g_propagate_error (error, g_steal_pointer (&nested_error));
2026 return NULL;
2027 }
2028 }
2029
2030 /* Licences */
2031 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2032 "license"))
2033 {
2034 if (!modulemd_module_stream_v2_parse_licenses (&parser,
2035 modulestream,
2036 strict,
2037 only_packager,
2038 &nested_error))
2039 {
2040 g_propagate_error (error, g_steal_pointer (&nested_error));
2041 return NULL;
2042 }
2043 }
2044
2045 /* Extensible Metadata */
2046 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2047 "xmd") &&
2048 !only_packager)
2049 {
2050 xmd = mmd_parse_xmd (&parser, &nested_error);
2051 if (!xmd)
2052 {
2053 g_propagate_error (error, g_steal_pointer (&nested_error));
2054 return NULL;
2055 }
2056 modulemd_module_stream_v2_set_xmd (modulestream, xmd);
2057 g_clear_pointer (&xmd, g_variant_unref);
2058 }
2059
2060 /* Dependencies */
2061 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2062 "dependencies"))
2063 {
2064 if (!modulemd_module_stream_v2_parse_deps (
2065 &parser, modulestream, strict, &nested_error))
2066 {
2067 g_propagate_error (error, g_steal_pointer (&nested_error));
2068 return NULL;
2069 }
2070 }
2071
2072 /* References */
2073 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2074 "references"))
2075 {
2076 if (!modulemd_module_stream_v2_parse_refs (
2077 &parser, modulestream, strict, &nested_error))
2078 {
2079 g_propagate_error (error, g_steal_pointer (&nested_error));
2080 return NULL;
2081 }
2082 }
2083
2084 /* Profiles */
2085 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2086 "profiles"))
2087 {
2088 if (!modulemd_module_stream_v2_parse_profiles (
2089 &parser, modulestream, strict, &nested_error))
2090 {
2091 g_propagate_error (error, g_steal_pointer (&nested_error));
2092 return NULL;
2093 }
2094 }
2095
2096 /* API */
2097 else if (g_str_equal ((const gchar *)event.data.scalar.value, "api"))
2098 {
2099 set = modulemd_yaml_parse_string_set_from_map (
2100 &parser, "rpms", strict, &nested_error);
2101 modulemd_module_stream_v2_replace_rpm_api (modulestream, set);
2102 g_clear_pointer (&set, g_hash_table_unref);
2103 }
2104
2105 /* Filter */
2106 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2107 "filter"))
2108 {
2109 set = modulemd_yaml_parse_string_set_from_map (
2110 &parser, "rpms", strict, &nested_error);
2111 modulemd_module_stream_v2_replace_rpm_filters (modulestream,
2112 set);
2113 g_clear_pointer (&set, g_hash_table_unref);
2114 }
2115
2116 /* Demodularized Packages */
2117 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2118 "demodularized"))
2119 {
2120 set = modulemd_yaml_parse_string_set_from_map (
2121 &parser, "rpms", strict, &nested_error);
2122 modulemd_module_stream_v2_replace_demodularized_rpms (
2123 modulestream, set);
2124 g_clear_pointer (&set, g_hash_table_unref);
2125 }
2126
2127 /* Build Options */
2128 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2129 "buildopts") &&
2130 !only_packager)
2131 {
2132 buildopts =
2133 modulemd_buildopts_parse_yaml (&parser, strict, &nested_error);
2134 if (!buildopts)
2135 {
2136 g_propagate_error (error, g_steal_pointer (&nested_error));
2137 return NULL;
2138 }
2139
2140 modulemd_module_stream_v2_set_buildopts (modulestream,
2141 buildopts);
2142 g_clear_object (&buildopts);
2143 }
2144
2145 /* Components */
2146 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2147 "components"))
2148 {
2149 if (!modulemd_module_stream_v2_parse_components (
2150 &parser, modulestream, strict, &nested_error))
2151 {
2152 g_propagate_error (error, g_steal_pointer (&nested_error));
2153 return NULL;
2154 }
2155 }
2156
2157 /* Artifacts */
2158 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2159 "artifacts") &&
2160 !only_packager)
2161 {
2162 if (!modulemd_module_stream_v2_parse_artifacts (
2163 &parser, modulestream, strict, &nested_error))
2164 {
2165 g_propagate_error (error, g_steal_pointer (&nested_error));
2166 return NULL;
2167 }
2168
2169 g_clear_pointer (&set, g_hash_table_unref);
2170 }
2171
2172 else
2173 {
2174 SKIP_UNKNOWN (&parser,
2175 NULL,
2176 "Unexpected key in data: %s",
2177 (const gchar *)event.data.scalar.value);
2178 break;
2179 }
2180 break;
2181
2182 default:
2183 MMD_YAML_ERROR_EVENT_EXIT (
2184 error,
2185 event,
2186 "Unexpected YAML event in ModuleStreamV2: %s",
2187 mmd_yaml_get_event_name (event.type));
2188 break;
2189 }
2190 yaml_event_delete (&event);
2191 }
2192
2193 return g_steal_pointer (&modulestream);
2194 }
2195
2196
2197 static gboolean
modulemd_module_stream_v2_parse_licenses(yaml_parser_t * parser,ModulemdModuleStreamV2 * modulestream,gboolean strict,gboolean only_packager,GError ** error)2198 modulemd_module_stream_v2_parse_licenses (yaml_parser_t *parser,
2199 ModulemdModuleStreamV2 *modulestream,
2200 gboolean strict,
2201 gboolean only_packager,
2202 GError **error)
2203 {
2204 MODULEMD_INIT_TRACE ();
2205 MMD_INIT_YAML_EVENT (event);
2206 gboolean done = FALSE;
2207 gboolean in_map = FALSE;
2208 g_autoptr (GError) nested_error = NULL;
2209 g_autoptr (GHashTable) set = NULL;
2210
2211 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2212
2213 /* Process through the mapping */
2214 while (!done)
2215 {
2216 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2217
2218 switch (event.type)
2219 {
2220 case YAML_MAPPING_START_EVENT:
2221 if (in_map)
2222 {
2223 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2224 error,
2225 event,
2226 "Unexpected extra MAPPING_START event in licenses");
2227 }
2228 in_map = TRUE;
2229 break;
2230
2231 case YAML_MAPPING_END_EVENT:
2232 if (!in_map)
2233 {
2234 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2235 error, event, "Unexpected MAPPING_END event in licenses");
2236 }
2237 done = TRUE;
2238 break;
2239
2240 case YAML_SCALAR_EVENT:
2241 if (!in_map)
2242 {
2243 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2244 error, event, "Received scalar outside of mapping");
2245 }
2246
2247 if (g_str_equal ((const gchar *)event.data.scalar.value, "module"))
2248 {
2249 set = modulemd_yaml_parse_string_set (parser, &nested_error);
2250 if (!set)
2251 {
2252 g_propagate_error (error, g_steal_pointer (&nested_error));
2253 return FALSE;
2254 }
2255 modulemd_module_stream_v2_replace_module_licenses (modulestream,
2256 set);
2257 g_clear_pointer (&set, g_hash_table_unref);
2258 }
2259 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2260 "content") &&
2261 !only_packager)
2262 {
2263 set = modulemd_yaml_parse_string_set (parser, &nested_error);
2264 modulemd_module_stream_v2_replace_content_licenses (modulestream,
2265 set);
2266 g_clear_pointer (&set, g_hash_table_unref);
2267 }
2268 else
2269 {
2270 SKIP_UNKNOWN (parser,
2271 FALSE,
2272 "Unexpected key in licenses: %s",
2273 (const gchar *)event.data.scalar.value);
2274 break;
2275 }
2276
2277 break;
2278
2279 default:
2280 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2281 error,
2282 event,
2283 "Unexpected YAML event in licenses: %s",
2284 mmd_yaml_get_event_name (event.type));
2285 break;
2286 }
2287 yaml_event_delete (&event);
2288 }
2289
2290 return TRUE;
2291 }
2292
2293
2294 static gboolean
modulemd_module_stream_v2_parse_servicelevels(yaml_parser_t * parser,ModulemdModuleStreamV2 * modulestream,gboolean strict,GError ** error)2295 modulemd_module_stream_v2_parse_servicelevels (
2296 yaml_parser_t *parser,
2297 ModulemdModuleStreamV2 *modulestream,
2298 gboolean strict,
2299 GError **error)
2300 {
2301 MODULEMD_INIT_TRACE ();
2302 MMD_INIT_YAML_EVENT (event);
2303 gboolean done = FALSE;
2304 gboolean in_map = FALSE;
2305 const gchar *name = NULL;
2306 g_autoptr (ModulemdServiceLevel) sl = NULL;
2307 g_autoptr (GError) nested_error = NULL;
2308
2309 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2310
2311 /* Process through the mapping */
2312 while (!done)
2313 {
2314 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2315
2316 switch (event.type)
2317 {
2318 case YAML_MAPPING_START_EVENT:
2319 if (in_map)
2320 {
2321 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2322 error,
2323 event,
2324 "Unexpected extra MAPPING_START event in servicelevels");
2325 }
2326 in_map = TRUE;
2327 break;
2328
2329 case YAML_MAPPING_END_EVENT:
2330 if (!in_map)
2331 {
2332 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2333 error, event, "Unexpected MAPPING_END event in servicelevels");
2334 }
2335 done = TRUE;
2336 break;
2337
2338 case YAML_SCALAR_EVENT:
2339 if (!in_map)
2340 {
2341 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2342 error, event, "Received scalar outside of mapping");
2343 }
2344
2345 name = (const gchar *)event.data.scalar.value;
2346
2347 sl = modulemd_service_level_parse_yaml (
2348 parser, name, strict, &nested_error);
2349 if (!sl)
2350 {
2351 g_propagate_error (error, g_steal_pointer (&nested_error));
2352 return FALSE;
2353 }
2354
2355 modulemd_module_stream_v2_add_servicelevel (modulestream, sl);
2356 g_clear_object (&sl);
2357
2358 break;
2359
2360 default:
2361 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2362 error,
2363 event,
2364 "Unexpected YAML event in servicelevels: %s",
2365 mmd_yaml_get_event_name (event.type));
2366 break;
2367 }
2368 yaml_event_delete (&event);
2369 }
2370
2371 return TRUE;
2372 }
2373
2374 static gboolean
modulemd_module_stream_v2_parse_deps(yaml_parser_t * parser,ModulemdModuleStreamV2 * modulestream,gboolean strict,GError ** error)2375 modulemd_module_stream_v2_parse_deps (yaml_parser_t *parser,
2376 ModulemdModuleStreamV2 *modulestream,
2377 gboolean strict,
2378 GError **error)
2379 {
2380 MODULEMD_INIT_TRACE ();
2381 MMD_INIT_YAML_EVENT (event);
2382 gboolean done = FALSE;
2383 g_autoptr (ModulemdDependencies) deps = NULL;
2384 g_autoptr (GError) nested_error = NULL;
2385
2386 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2387
2388 /* Process through the sequence */
2389 /* We *must* get a SEQUENCE_START here */
2390 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2391 if (event.type != YAML_SEQUENCE_START_EVENT)
2392 {
2393 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2394 error,
2395 event,
2396 "Got %s instead of SEQUENCE_START in dependencies.",
2397 mmd_yaml_get_event_name (event.type));
2398 }
2399
2400 while (!done)
2401 {
2402 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2403
2404 switch (event.type)
2405 {
2406 case YAML_SEQUENCE_END_EVENT: done = TRUE; break;
2407
2408 case YAML_MAPPING_START_EVENT:
2409 deps =
2410 modulemd_dependencies_parse_yaml (parser, strict, &nested_error);
2411 if (!deps)
2412 {
2413 g_propagate_error (error, g_steal_pointer (&nested_error));
2414 return FALSE;
2415 }
2416
2417 modulemd_module_stream_v2_add_dependencies (modulestream, deps);
2418 g_clear_object (&deps);
2419 break;
2420
2421 default:
2422 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2423 error,
2424 event,
2425 "Unexpected YAML event in dependencies: %s",
2426 mmd_yaml_get_event_name (event.type));
2427 break;
2428 }
2429 yaml_event_delete (&event);
2430 }
2431
2432 return TRUE;
2433 }
2434
2435
2436 static gboolean
modulemd_module_stream_v2_parse_refs(yaml_parser_t * parser,ModulemdModuleStreamV2 * modulestream,gboolean strict,GError ** error)2437 modulemd_module_stream_v2_parse_refs (yaml_parser_t *parser,
2438 ModulemdModuleStreamV2 *modulestream,
2439 gboolean strict,
2440 GError **error)
2441 {
2442 MODULEMD_INIT_TRACE ();
2443 MMD_INIT_YAML_EVENT (event);
2444 gboolean done = FALSE;
2445 g_autofree gchar *scalar = NULL;
2446 g_autoptr (GError) nested_error = NULL;
2447
2448 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2449
2450 /* Process through the map */
2451 /* We *must* get a MAPPING_START here */
2452 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2453 if (event.type != YAML_MAPPING_START_EVENT)
2454 {
2455 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2456 error,
2457 event,
2458 "Got %s instead of MAPPING_START in dependencies.",
2459 mmd_yaml_get_event_name (event.type));
2460 }
2461
2462 while (!done)
2463 {
2464 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2465
2466 switch (event.type)
2467 {
2468 case YAML_MAPPING_END_EVENT: done = TRUE; break;
2469
2470 case YAML_SCALAR_EVENT:
2471 if (g_str_equal ((const gchar *)event.data.scalar.value,
2472 "community"))
2473 {
2474 scalar = modulemd_yaml_parse_string (parser, &nested_error);
2475 if (!scalar)
2476 {
2477 g_propagate_error (error, g_steal_pointer (&nested_error));
2478 return FALSE;
2479 }
2480
2481 modulemd_module_stream_v2_set_community (modulestream, scalar);
2482 g_clear_pointer (&scalar, g_free);
2483 }
2484
2485 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2486 "documentation"))
2487 {
2488 scalar = modulemd_yaml_parse_string (parser, &nested_error);
2489 if (!scalar)
2490 {
2491 g_propagate_error (error, g_steal_pointer (&nested_error));
2492 return FALSE;
2493 }
2494
2495 modulemd_module_stream_v2_set_documentation (modulestream,
2496 scalar);
2497 g_clear_pointer (&scalar, g_free);
2498 }
2499
2500 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2501 "tracker"))
2502 {
2503 scalar = modulemd_yaml_parse_string (parser, &nested_error);
2504 if (!scalar)
2505 {
2506 g_propagate_error (error, g_steal_pointer (&nested_error));
2507 return FALSE;
2508 }
2509
2510 modulemd_module_stream_v2_set_tracker (modulestream, scalar);
2511 g_clear_pointer (&scalar, g_free);
2512 }
2513
2514 else
2515 {
2516 SKIP_UNKNOWN (parser,
2517 FALSE,
2518 "Unexpected key in references: %s",
2519 (const gchar *)event.data.scalar.value);
2520 break;
2521 }
2522 break;
2523
2524 default:
2525 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2526 error,
2527 event,
2528 "Unexpected YAML event in dependencies: %s",
2529 mmd_yaml_get_event_name (event.type));
2530 break;
2531 }
2532 yaml_event_delete (&event);
2533 }
2534
2535 return TRUE;
2536 }
2537
2538
2539 static gboolean
modulemd_module_stream_v2_parse_profiles(yaml_parser_t * parser,ModulemdModuleStreamV2 * modulestream,gboolean strict,GError ** error)2540 modulemd_module_stream_v2_parse_profiles (yaml_parser_t *parser,
2541 ModulemdModuleStreamV2 *modulestream,
2542 gboolean strict,
2543 GError **error)
2544 {
2545 MODULEMD_INIT_TRACE ();
2546 MMD_INIT_YAML_EVENT (event);
2547 gboolean done = FALSE;
2548 g_autoptr (GError) nested_error = NULL;
2549 g_autoptr (ModulemdProfile) profile = NULL;
2550
2551 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2552
2553 /* Process through the map */
2554 /* We *must* get a MAPPING_START here */
2555 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2556 if (event.type != YAML_MAPPING_START_EVENT)
2557 {
2558 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2559 error,
2560 event,
2561 "Got %s instead of MAPPING_START in profiles.",
2562 mmd_yaml_get_event_name (event.type));
2563 }
2564
2565 while (!done)
2566 {
2567 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2568
2569 switch (event.type)
2570 {
2571 case YAML_MAPPING_END_EVENT: done = TRUE; break;
2572
2573 case YAML_SCALAR_EVENT:
2574 profile = modulemd_profile_parse_yaml (
2575 parser,
2576 (const gchar *)event.data.scalar.value,
2577 strict,
2578 &nested_error);
2579 if (!profile)
2580 {
2581 g_propagate_error (error, g_steal_pointer (&nested_error));
2582 return FALSE;
2583 }
2584
2585 modulemd_module_stream_v2_add_profile (modulestream, profile);
2586 g_clear_pointer (&profile, g_object_unref);
2587 break;
2588
2589 default:
2590 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2591 error,
2592 event,
2593 "Unexpected YAML event in dependencies: %s",
2594 mmd_yaml_get_event_name (event.type));
2595 break;
2596 }
2597 yaml_event_delete (&event);
2598 }
2599
2600 return TRUE;
2601 }
2602
2603
2604 static gboolean
2605 modulemd_module_stream_v2_parse_rpm_components (
2606 yaml_parser_t *parser,
2607 ModulemdModuleStreamV2 *modulestream,
2608 gboolean strict,
2609 GError **error);
2610 static gboolean
2611 modulemd_module_stream_v2_parse_module_components (
2612 yaml_parser_t *parser,
2613 ModulemdModuleStreamV2 *modulestream,
2614 gboolean strict,
2615 GError **error);
2616
2617
2618 static gboolean
modulemd_module_stream_v2_parse_components(yaml_parser_t * parser,ModulemdModuleStreamV2 * modulestream,gboolean strict,GError ** error)2619 modulemd_module_stream_v2_parse_components (
2620 yaml_parser_t *parser,
2621 ModulemdModuleStreamV2 *modulestream,
2622 gboolean strict,
2623 GError **error)
2624 {
2625 MODULEMD_INIT_TRACE ();
2626 MMD_INIT_YAML_EVENT (event);
2627 gboolean done = FALSE;
2628 g_autoptr (GError) nested_error = NULL;
2629
2630 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2631
2632 /* Process through the sequence */
2633 /* We *must* get a MAPPING_START here */
2634 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2635 if (event.type != YAML_MAPPING_START_EVENT)
2636 {
2637 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2638 error,
2639 event,
2640 "Got %s instead of MAPPING_START in components.",
2641 mmd_yaml_get_event_name (event.type));
2642 }
2643
2644 while (!done)
2645 {
2646 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2647
2648 switch (event.type)
2649 {
2650 case YAML_MAPPING_END_EVENT: done = TRUE; break;
2651
2652 case YAML_SCALAR_EVENT:
2653 if (g_str_equal ((const gchar *)event.data.scalar.value, "rpms"))
2654 {
2655 if (!modulemd_module_stream_v2_parse_rpm_components (
2656 parser, modulestream, strict, &nested_error))
2657 {
2658 g_propagate_error (error, g_steal_pointer (&nested_error));
2659 return FALSE;
2660 }
2661 }
2662
2663 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2664 "modules"))
2665 {
2666 if (!modulemd_module_stream_v2_parse_module_components (
2667 parser, modulestream, strict, &nested_error))
2668 {
2669 g_propagate_error (error, g_steal_pointer (&nested_error));
2670 return FALSE;
2671 }
2672 }
2673
2674 else
2675 {
2676 SKIP_UNKNOWN (parser,
2677 FALSE,
2678 "Unexpected key in components: %s",
2679 (const gchar *)event.data.scalar.value);
2680 }
2681
2682 break;
2683
2684
2685 default:
2686 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2687 error,
2688 event,
2689 "Unexpected YAML event in components: %s",
2690 mmd_yaml_get_event_name (event.type));
2691 break;
2692 }
2693 yaml_event_delete (&event);
2694 }
2695
2696 return TRUE;
2697 }
2698
2699
2700 static gboolean
modulemd_module_stream_v2_parse_rpm_components(yaml_parser_t * parser,ModulemdModuleStreamV2 * modulestream,gboolean strict,GError ** error)2701 modulemd_module_stream_v2_parse_rpm_components (
2702 yaml_parser_t *parser,
2703 ModulemdModuleStreamV2 *modulestream,
2704 gboolean strict,
2705 GError **error)
2706 {
2707 MODULEMD_INIT_TRACE ();
2708 MMD_INIT_YAML_EVENT (event);
2709 gboolean done = FALSE;
2710 g_autoptr (GError) nested_error = NULL;
2711 g_autoptr (ModulemdComponentRpm) component = NULL;
2712
2713 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2714
2715 /* We *must* get a MAPPING_START here */
2716 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2717 if (event.type != YAML_MAPPING_START_EVENT)
2718 {
2719 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2720 error,
2721 event,
2722 "Got %s instead of MAPPING_START in rpm components.",
2723 mmd_yaml_get_event_name (event.type));
2724 }
2725
2726 while (!done)
2727 {
2728 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2729
2730 switch (event.type)
2731 {
2732 case YAML_MAPPING_END_EVENT: done = TRUE; break;
2733
2734 case YAML_SCALAR_EVENT:
2735 component = modulemd_component_rpm_parse_yaml (
2736 parser,
2737 (const gchar *)event.data.scalar.value,
2738 strict,
2739 &nested_error);
2740 if (!component)
2741 {
2742 g_propagate_error (error, g_steal_pointer (&nested_error));
2743 return FALSE;
2744 }
2745 modulemd_module_stream_v2_add_component (
2746 modulestream, (ModulemdComponent *)component);
2747 g_clear_pointer (&component, g_object_unref);
2748 break;
2749
2750 default:
2751 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2752 error,
2753 event,
2754 "Unexpected YAML event in RPM component: %s",
2755 mmd_yaml_get_event_name (event.type));
2756 break;
2757 }
2758 yaml_event_delete (&event);
2759 }
2760
2761 return TRUE;
2762 }
2763
2764
2765 static gboolean
modulemd_module_stream_v2_parse_module_components(yaml_parser_t * parser,ModulemdModuleStreamV2 * modulestream,gboolean strict,GError ** error)2766 modulemd_module_stream_v2_parse_module_components (
2767 yaml_parser_t *parser,
2768 ModulemdModuleStreamV2 *modulestream,
2769 gboolean strict,
2770 GError **error)
2771 {
2772 MODULEMD_INIT_TRACE ();
2773 MMD_INIT_YAML_EVENT (event);
2774 gboolean done = FALSE;
2775 g_autoptr (GError) nested_error = NULL;
2776 g_autoptr (ModulemdComponentModule) component = NULL;
2777
2778 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2779
2780 /* We *must* get a MAPPING_START here */
2781 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2782 if (event.type != YAML_MAPPING_START_EVENT)
2783 {
2784 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2785 error,
2786 event,
2787 "Got %s instead of MAPPING_START in module components.",
2788 mmd_yaml_get_event_name (event.type));
2789 }
2790
2791 while (!done)
2792 {
2793 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2794
2795 switch (event.type)
2796 {
2797 case YAML_MAPPING_END_EVENT: done = TRUE; break;
2798
2799 case YAML_SCALAR_EVENT:
2800 component = modulemd_component_module_parse_yaml (
2801 parser,
2802 (const gchar *)event.data.scalar.value,
2803 strict,
2804 &nested_error);
2805 if (!component)
2806 {
2807 g_propagate_error (error, g_steal_pointer (&nested_error));
2808 return FALSE;
2809 }
2810 modulemd_module_stream_v2_add_component (
2811 modulestream, (ModulemdComponent *)component);
2812 g_clear_pointer (&component, g_object_unref);
2813 break;
2814
2815 default:
2816 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2817 error,
2818 event,
2819 "Unexpected YAML event in module component: %s",
2820 mmd_yaml_get_event_name (event.type));
2821 break;
2822 }
2823 yaml_event_delete (&event);
2824 }
2825
2826 return TRUE;
2827 }
2828
2829
2830 static gboolean
2831 modulemd_module_stream_v2_parse_rpm_map (yaml_parser_t *parser,
2832 ModulemdModuleStreamV2 *modulestream,
2833 gboolean strict,
2834 GError **error);
2835
2836
2837 static gboolean
modulemd_module_stream_v2_parse_artifacts(yaml_parser_t * parser,ModulemdModuleStreamV2 * modulestream,gboolean strict,GError ** error)2838 modulemd_module_stream_v2_parse_artifacts (
2839 yaml_parser_t *parser,
2840 ModulemdModuleStreamV2 *modulestream,
2841 gboolean strict,
2842 GError **error)
2843 {
2844 MODULEMD_INIT_TRACE ();
2845 MMD_INIT_YAML_EVENT (event);
2846 gboolean done = FALSE;
2847 g_autoptr (GHashTable) set = NULL;
2848 g_autoptr (GError) nested_error = NULL;
2849
2850 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2851
2852 /* We *must* get a MAPPING_START here */
2853 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2854 if (event.type != YAML_MAPPING_START_EVENT)
2855 {
2856 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2857 error,
2858 event,
2859 "Got %s instead of MAPPING_START in artifacts.",
2860 mmd_yaml_get_event_name (event.type));
2861 }
2862
2863 while (!done)
2864 {
2865 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2866
2867 switch (event.type)
2868 {
2869 case YAML_MAPPING_END_EVENT: done = TRUE; break;
2870
2871 case YAML_SCALAR_EVENT:
2872 if (g_str_equal ((const gchar *)event.data.scalar.value, "rpms"))
2873 {
2874 set = modulemd_yaml_parse_string_set (parser, &nested_error);
2875 if (!set)
2876 {
2877 g_propagate_error (error, g_steal_pointer (&nested_error));
2878 return FALSE;
2879 }
2880
2881 modulemd_module_stream_v2_replace_rpm_artifacts (modulestream,
2882 set);
2883 g_clear_pointer (&set, g_hash_table_unref);
2884 }
2885
2886 else if (g_str_equal ((const gchar *)event.data.scalar.value,
2887 "rpm-map"))
2888 {
2889 if (!modulemd_module_stream_v2_parse_rpm_map (
2890 parser, modulestream, strict, &nested_error))
2891 {
2892 g_propagate_error (error, g_steal_pointer (&nested_error));
2893 return FALSE;
2894 }
2895 }
2896
2897 else
2898 {
2899 /* Encountered a key other than the expected ones. */
2900 SKIP_UNKNOWN (parser,
2901 FALSE,
2902 "Unexpected key in map: %s",
2903 (const gchar *)event.data.scalar.value);
2904 }
2905
2906 break;
2907
2908 default:
2909 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2910 error, event, "Unexpected YAML event in map");
2911 break;
2912 }
2913 yaml_event_delete (&event);
2914 }
2915
2916 return TRUE;
2917 }
2918
2919
2920 static gboolean
2921 modulemd_module_stream_v2_parse_rpm_map_digest (
2922 yaml_parser_t *parser,
2923 ModulemdModuleStreamV2 *modulestream,
2924 gboolean strict,
2925 const gchar *digest,
2926 GError **error);
2927
2928 static gboolean
modulemd_module_stream_v2_parse_rpm_map(yaml_parser_t * parser,ModulemdModuleStreamV2 * modulestream,gboolean strict,GError ** error)2929 modulemd_module_stream_v2_parse_rpm_map (yaml_parser_t *parser,
2930 ModulemdModuleStreamV2 *modulestream,
2931 gboolean strict,
2932 GError **error)
2933 {
2934 MODULEMD_INIT_TRACE ();
2935 MMD_INIT_YAML_EVENT (event);
2936 gboolean done = FALSE;
2937 g_autoptr (GError) nested_error = NULL;
2938
2939 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2940
2941 /* We *must* get a MAPPING_START here */
2942 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2943 if (event.type != YAML_MAPPING_START_EVENT)
2944 {
2945 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2946 error,
2947 event,
2948 "Got %s instead of MAPPING_START in rpm-map.",
2949 mmd_yaml_get_event_name (event.type));
2950 }
2951
2952 while (!done)
2953 {
2954 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
2955
2956 switch (event.type)
2957 {
2958 case YAML_MAPPING_END_EVENT: done = TRUE; break;
2959
2960 case YAML_SCALAR_EVENT:
2961 /* Each entry in the map here represents a digest name */
2962 if (!modulemd_module_stream_v2_parse_rpm_map_digest (
2963 parser,
2964 modulestream,
2965 strict,
2966 (const gchar *)event.data.scalar.value,
2967 &nested_error))
2968 {
2969 g_propagate_error (error, g_steal_pointer (&nested_error));
2970 return FALSE;
2971 }
2972 break;
2973
2974 default:
2975 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
2976 error, event, "Unexpected YAML event in map");
2977 break;
2978 }
2979 yaml_event_delete (&event);
2980 }
2981
2982 return TRUE;
2983 }
2984
2985
2986 static gboolean
modulemd_module_stream_v2_parse_rpm_map_digest(yaml_parser_t * parser,ModulemdModuleStreamV2 * modulestream,gboolean strict,const gchar * digest,GError ** error)2987 modulemd_module_stream_v2_parse_rpm_map_digest (
2988 yaml_parser_t *parser,
2989 ModulemdModuleStreamV2 *modulestream,
2990 gboolean strict,
2991 const gchar *digest,
2992 GError **error)
2993 {
2994 MODULEMD_INIT_TRACE ();
2995 MMD_INIT_YAML_EVENT (event);
2996 gboolean done = FALSE;
2997 g_autoptr (GError) nested_error = NULL;
2998 const gchar *checksum = NULL;
2999 g_autoptr (ModulemdRpmMapEntry) entry = NULL;
3000
3001 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
3002
3003 /* We *must* get a MAPPING_START here */
3004 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
3005 if (event.type != YAML_MAPPING_START_EVENT)
3006 {
3007 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
3008 error,
3009 event,
3010 "Got %s instead of MAPPING_START in rpm-map.",
3011 mmd_yaml_get_event_name (event.type));
3012 }
3013
3014 while (!done)
3015 {
3016 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
3017
3018 switch (event.type)
3019 {
3020 case YAML_MAPPING_END_EVENT: done = TRUE; break;
3021
3022 case YAML_SCALAR_EVENT:
3023 /* Each key in this map is a checksum with the value being a
3024 * ModulemdRpmMapEntry
3025 */
3026 checksum = (const gchar *)event.data.scalar.value;
3027
3028 entry =
3029 modulemd_rpm_map_entry_parse_yaml (parser, strict, &nested_error);
3030 if (!entry)
3031 {
3032 g_propagate_error (error, g_steal_pointer (&nested_error));
3033 return FALSE;
3034 }
3035
3036 modulemd_module_stream_v2_set_rpm_artifact_map_entry (
3037 modulestream, entry, digest, checksum);
3038
3039 g_clear_object (&entry);
3040 break;
3041
3042 default:
3043 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
3044 error, event, "Unexpected YAML event in map");
3045 break;
3046 }
3047 yaml_event_delete (&event);
3048 }
3049
3050 return TRUE;
3051 }
3052
3053
3054 gboolean
3055 modulemd_module_stream_v2_emit_rpm_map (ModulemdModuleStreamV2 *self,
3056 yaml_emitter_t *emitter,
3057 GError **error);
3058
3059 gboolean
modulemd_module_stream_v2_emit_yaml(ModulemdModuleStreamV2 * self,yaml_emitter_t * emitter,GError ** error)3060 modulemd_module_stream_v2_emit_yaml (ModulemdModuleStreamV2 *self,
3061 yaml_emitter_t *emitter,
3062 GError **error)
3063 {
3064 MODULEMD_INIT_TRACE ();
3065
3066 if (!modulemd_module_stream_emit_yaml_base (
3067 MODULEMD_MODULE_STREAM (self), emitter, error))
3068 {
3069 return FALSE;
3070 }
3071
3072 if (modulemd_module_stream_v2_is_static_context (self))
3073 {
3074 EMIT_KEY_VALUE (emitter, error, "static_context", "true");
3075 }
3076
3077 EMIT_KEY_VALUE_IF_SET (
3078 emitter, error, "arch", modulemd_module_stream_v2_get_arch (self));
3079 EMIT_KEY_VALUE (emitter, error, "summary", self->summary);
3080 EMIT_KEY_VALUE_FULL (emitter,
3081 error,
3082 "description",
3083 self->description,
3084 YAML_FOLDED_SCALAR_STYLE);
3085
3086 EMIT_HASHTABLE_VALUES_IF_NON_EMPTY (emitter,
3087 error,
3088 "servicelevels",
3089 self->servicelevels,
3090 modulemd_service_level_emit_yaml);
3091
3092 if (!NON_EMPTY_TABLE (self->module_licenses))
3093 {
3094 g_set_error (error,
3095 MODULEMD_YAML_ERROR,
3096 MMD_YAML_ERROR_EMIT,
3097 "Module licenses is not allowed to be empty");
3098 return FALSE;
3099 }
3100
3101 EMIT_SCALAR (emitter, error, "license");
3102 EMIT_MAPPING_START (emitter, error);
3103 EMIT_STRING_SET (emitter, error, "module", self->module_licenses);
3104 EMIT_STRING_SET_IF_NON_EMPTY (
3105 emitter, error, "content", self->content_licenses);
3106 EMIT_MAPPING_END (emitter, error);
3107
3108 if (self->xmd != NULL)
3109 {
3110 EMIT_SCALAR (emitter, error, "xmd");
3111 if (!modulemd_yaml_emit_variant (emitter, self->xmd, error))
3112 {
3113 return FALSE;
3114 }
3115 }
3116
3117 EMIT_ARRAY_VALUES_IF_NON_EMPTY (emitter,
3118 error,
3119 "dependencies",
3120 self->dependencies,
3121 modulemd_dependencies_emit_yaml);
3122
3123 if (self->community || self->documentation || self->tracker)
3124 {
3125 EMIT_SCALAR (emitter, error, "references");
3126 EMIT_MAPPING_START (emitter, error);
3127 EMIT_KEY_VALUE_IF_SET (emitter, error, "community", self->community);
3128 EMIT_KEY_VALUE_IF_SET (
3129 emitter, error, "documentation", self->documentation);
3130 EMIT_KEY_VALUE_IF_SET (emitter, error, "tracker", self->tracker);
3131 EMIT_MAPPING_END (emitter, error);
3132 }
3133
3134 EMIT_HASHTABLE_VALUES_IF_NON_EMPTY (
3135 emitter, error, "profiles", self->profiles, modulemd_profile_emit_yaml);
3136
3137 if (NON_EMPTY_TABLE (self->rpm_api))
3138 {
3139 EMIT_SCALAR (emitter, error, "api");
3140 EMIT_MAPPING_START (emitter, error);
3141 EMIT_STRING_SET (emitter, error, "rpms", self->rpm_api);
3142 EMIT_MAPPING_END (emitter, error);
3143 }
3144
3145 if (NON_EMPTY_TABLE (self->rpm_filters))
3146 {
3147 EMIT_SCALAR (emitter, error, "filter");
3148 EMIT_MAPPING_START (emitter, error);
3149 EMIT_STRING_SET (emitter, error, "rpms", self->rpm_filters);
3150 EMIT_MAPPING_END (emitter, error);
3151 }
3152
3153 if (NON_EMPTY_TABLE (self->demodularized_rpms))
3154 {
3155 EMIT_SCALAR (emitter, error, "demodularized");
3156 EMIT_MAPPING_START (emitter, error);
3157 EMIT_STRING_SET (emitter, error, "rpms", self->demodularized_rpms);
3158 EMIT_MAPPING_END (emitter, error);
3159 }
3160
3161 if (self->buildopts != NULL)
3162 {
3163 EMIT_SCALAR (emitter, error, "buildopts");
3164 EMIT_MAPPING_START (emitter, error);
3165 if (!modulemd_buildopts_emit_yaml (self->buildopts, emitter, error))
3166 {
3167 return FALSE;
3168 }
3169 EMIT_MAPPING_END (emitter, error);
3170 }
3171
3172 if (NON_EMPTY_TABLE (self->rpm_components) ||
3173 NON_EMPTY_TABLE (self->module_components))
3174 {
3175 EMIT_SCALAR (emitter, error, "components");
3176 EMIT_MAPPING_START (emitter, error);
3177 EMIT_HASHTABLE_VALUES_IF_NON_EMPTY (emitter,
3178 error,
3179 "rpms",
3180 self->rpm_components,
3181 modulemd_component_rpm_emit_yaml);
3182 EMIT_HASHTABLE_VALUES_IF_NON_EMPTY (emitter,
3183 error,
3184 "modules",
3185 self->module_components,
3186 modulemd_component_module_emit_yaml);
3187 EMIT_MAPPING_END (emitter, error);
3188 }
3189
3190 if (NON_EMPTY_TABLE (self->rpm_artifacts) ||
3191 NON_EMPTY_TABLE (self->rpm_artifact_map))
3192 {
3193 EMIT_SCALAR (emitter, error, "artifacts");
3194 EMIT_MAPPING_START (emitter, error);
3195
3196 /* Emit the rpm artifacts */
3197 EMIT_STRING_SET_IF_NON_EMPTY (
3198 emitter, error, "rpms", self->rpm_artifacts);
3199
3200 /* Emit the rpm-map */
3201 if (!modulemd_module_stream_v2_emit_rpm_map (self, emitter, error))
3202 {
3203 return FALSE;
3204 }
3205
3206 EMIT_MAPPING_END (emitter, error);
3207 }
3208
3209 /* The "data" mapping */
3210 EMIT_MAPPING_END (emitter, error);
3211 /* The overall document mapping */
3212 EMIT_MAPPING_END (emitter, error);
3213 if (!mmd_emitter_end_document (emitter, error))
3214 {
3215 return FALSE;
3216 }
3217
3218 return TRUE;
3219 }
3220
3221
3222 gboolean
modulemd_module_stream_v2_emit_rpm_map(ModulemdModuleStreamV2 * self,yaml_emitter_t * emitter,GError ** error)3223 modulemd_module_stream_v2_emit_rpm_map (ModulemdModuleStreamV2 *self,
3224 yaml_emitter_t *emitter,
3225 GError **error)
3226 {
3227 GHashTable *digest_table = NULL;
3228 g_autoptr (GPtrArray) digests = NULL;
3229 const gchar *digest = NULL;
3230 g_autoptr (GPtrArray) checksums = NULL;
3231 const gchar *checksum = NULL;
3232 ModulemdRpmMapEntry *entry = NULL;
3233
3234 if (!NON_EMPTY_TABLE (self->rpm_artifact_map))
3235 {
3236 /* Nothing to output here */
3237 return TRUE;
3238 }
3239
3240 digests =
3241 modulemd_ordered_str_keys (self->rpm_artifact_map, modulemd_strcmp_sort);
3242
3243 EMIT_SCALAR (emitter, error, "rpm-map");
3244 EMIT_MAPPING_START (emitter, error);
3245
3246 for (guint i = 0; i < digests->len; i++)
3247 {
3248 digest = g_ptr_array_index (digests, i);
3249 EMIT_SCALAR (emitter, error, digest);
3250
3251 digest_table = g_hash_table_lookup (self->rpm_artifact_map, digest);
3252
3253 EMIT_MAPPING_START (emitter, error);
3254
3255 checksums =
3256 modulemd_ordered_str_keys (digest_table, modulemd_strcmp_sort);
3257
3258 for (guint j = 0; j < digests->len; j++)
3259 {
3260 checksum = g_ptr_array_index (checksums, j);
3261 EMIT_SCALAR (emitter, error, checksum);
3262
3263 entry = g_hash_table_lookup (digest_table, checksum);
3264
3265 if (!modulemd_rpm_map_entry_emit_yaml (entry, emitter, error))
3266 {
3267 return FALSE;
3268 }
3269 }
3270
3271 EMIT_MAPPING_END (emitter, error);
3272
3273 g_clear_pointer (&checksums, g_ptr_array_unref);
3274 }
3275
3276 EMIT_MAPPING_END (emitter, error);
3277
3278 return TRUE;
3279 }
3280