1 /*
2 * This file is part of libmodulemd
3 * Copyright (C) 2020 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 "private/modulemd-build-config-private.h"
15 #include "private/modulemd-component-private.h"
16 #include "private/modulemd-component-module-private.h"
17 #include "private/modulemd-component-rpm-private.h"
18 #include "private/modulemd-defaults-v1-private.h"
19 #include "private/modulemd-module-stream-private.h"
20 #include "private/modulemd-packager-v3-private.h"
21 #include "private/modulemd-profile-private.h"
22 #include "private/modulemd-subdocument-info-private.h"
23 #include "private/modulemd-util.h"
24 #include "private/modulemd-yaml.h"
25
26 struct _ModulemdPackagerV3
27 {
28 GObject parent_instance;
29
30 gchar *module_name;
31 gchar *stream_name;
32 gchar *summary;
33 gchar *description;
34 GHashTable *module_licenses; /* string set */
35 GVariant *xmd;
36 GHashTable *build_configs; /* <string, Modulemd.BuildConfig> */
37 gchar *community;
38 gchar *documentation;
39 gchar *tracker;
40 GHashTable *profiles; /* <string, Modulemd.Profile> */
41 GHashTable *rpm_api; /* string set */
42 GHashTable *rpm_filters; /* string set */
43 GHashTable *demodularized_rpms; /* string set */
44 GHashTable *rpm_components; /* <string, Modulemd.ComponentRpm> */
45 GHashTable *module_components; /* <string, Modulemd.ComponentModule */
46 };
47
G_DEFINE_TYPE(ModulemdPackagerV3,modulemd_packager_v3,G_TYPE_OBJECT)48 G_DEFINE_TYPE (ModulemdPackagerV3, modulemd_packager_v3, G_TYPE_OBJECT)
49
50 ModulemdPackagerV3 *
51 modulemd_packager_v3_new (void)
52 {
53 return g_object_new (MODULEMD_TYPE_PACKAGER_V3, NULL);
54 }
55
56 static void
modulemd_packager_v3_finalize(GObject * object)57 modulemd_packager_v3_finalize (GObject *object)
58 {
59 ModulemdPackagerV3 *self = (ModulemdPackagerV3 *)object;
60
61 g_clear_pointer (&self->module_name, g_free);
62 g_clear_pointer (&self->stream_name, g_free);
63 g_clear_pointer (&self->summary, g_free);
64 g_clear_pointer (&self->description, g_free);
65 g_clear_pointer (&self->module_licenses, g_hash_table_unref);
66 g_clear_pointer (&self->xmd, g_variant_unref);
67 g_clear_pointer (&self->build_configs, g_hash_table_unref);
68 g_clear_pointer (&self->community, g_free);
69 g_clear_pointer (&self->documentation, g_free);
70 g_clear_pointer (&self->tracker, g_free);
71 g_clear_pointer (&self->profiles, g_hash_table_unref);
72 g_clear_pointer (&self->rpm_api, g_hash_table_unref);
73 g_clear_pointer (&self->rpm_filters, g_hash_table_unref);
74 g_clear_pointer (&self->demodularized_rpms, g_hash_table_unref);
75 g_clear_pointer (&self->rpm_components, g_hash_table_unref);
76 g_clear_pointer (&self->module_components, g_hash_table_unref);
77
78 G_OBJECT_CLASS (modulemd_packager_v3_parent_class)->finalize (object);
79 }
80
81 static void
modulemd_packager_v3_class_init(ModulemdPackagerV3Class * klass)82 modulemd_packager_v3_class_init (ModulemdPackagerV3Class *klass)
83 {
84 GObjectClass *object_class = G_OBJECT_CLASS (klass);
85
86 object_class->finalize = modulemd_packager_v3_finalize;
87 }
88
89 static void
modulemd_packager_v3_init(ModulemdPackagerV3 * self)90 modulemd_packager_v3_init (ModulemdPackagerV3 *self)
91 {
92 self->module_licenses =
93 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
94
95 self->build_configs =
96 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
97
98 self->profiles =
99 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
100
101 self->rpm_api =
102 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
103
104 self->rpm_filters =
105 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
106
107 self->demodularized_rpms =
108 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
109
110 self->rpm_components =
111 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
112
113 self->module_components =
114 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
115 }
116
117
118 ModulemdPackagerV3 *
modulemd_packager_v3_copy(ModulemdPackagerV3 * self)119 modulemd_packager_v3_copy (ModulemdPackagerV3 *self)
120 {
121 g_autoptr (ModulemdPackagerV3) copy = modulemd_packager_v3_new ();
122
123 modulemd_packager_v3_set_module_name (
124 copy, modulemd_packager_v3_get_module_name (self));
125
126 modulemd_packager_v3_set_stream_name (
127 copy, modulemd_packager_v3_get_stream_name (self));
128
129 modulemd_packager_v3_set_summary (copy,
130 modulemd_packager_v3_get_summary (self));
131
132 modulemd_packager_v3_set_description (
133 copy, modulemd_packager_v3_get_description (self));
134
135 MODULEMD_REPLACE_SET (copy->module_licenses, self->module_licenses);
136
137 modulemd_packager_v3_set_xmd (copy, modulemd_packager_v3_get_xmd (self));
138
139 COPY_HASHTABLE_BY_VALUE_ADDER (
140 copy, self, build_configs, modulemd_packager_v3_add_build_config);
141
142 modulemd_packager_v3_set_community (
143 copy, modulemd_packager_v3_get_community (self));
144
145 modulemd_packager_v3_set_documentation (
146 copy, modulemd_packager_v3_get_documentation (self));
147
148 modulemd_packager_v3_set_tracker (copy,
149 modulemd_packager_v3_get_tracker (self));
150
151 COPY_HASHTABLE_BY_VALUE_ADDER (
152 copy, self, profiles, modulemd_packager_v3_add_profile);
153
154 modulemd_packager_v3_replace_rpm_api (copy, self->rpm_api);
155
156 modulemd_packager_v3_replace_rpm_filters (copy, self->rpm_filters);
157
158 modulemd_packager_v3_replace_demodularized_rpms (copy,
159 self->demodularized_rpms);
160
161 COPY_HASHTABLE_BY_VALUE_ADDER (
162 copy, self, rpm_components, modulemd_packager_v3_add_component);
163
164 COPY_HASHTABLE_BY_VALUE_ADDER (
165 copy, self, module_components, modulemd_packager_v3_add_component);
166
167 return g_steal_pointer (©);
168 }
169
170
171 void
modulemd_packager_v3_set_module_name(ModulemdPackagerV3 * self,const gchar * module_name)172 modulemd_packager_v3_set_module_name (ModulemdPackagerV3 *self,
173 const gchar *module_name)
174 {
175 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
176
177 g_clear_pointer (&self->module_name, g_free);
178
179 if (module_name)
180 {
181 self->module_name = g_strdup (module_name);
182 }
183 }
184
185
186 const gchar *
modulemd_packager_v3_get_module_name(ModulemdPackagerV3 * self)187 modulemd_packager_v3_get_module_name (ModulemdPackagerV3 *self)
188 {
189 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
190
191 return self->module_name;
192 }
193
194
195 void
modulemd_packager_v3_set_stream_name(ModulemdPackagerV3 * self,const gchar * stream_name)196 modulemd_packager_v3_set_stream_name (ModulemdPackagerV3 *self,
197 const gchar *stream_name)
198 {
199 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
200
201 g_clear_pointer (&self->stream_name, g_free);
202
203 if (stream_name)
204 {
205 self->stream_name = g_strdup (stream_name);
206 }
207 }
208
209
210 const gchar *
modulemd_packager_v3_get_stream_name(ModulemdPackagerV3 * self)211 modulemd_packager_v3_get_stream_name (ModulemdPackagerV3 *self)
212 {
213 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
214
215 return self->stream_name;
216 }
217
218
219 void
modulemd_packager_v3_set_summary(ModulemdPackagerV3 * self,const gchar * summary)220 modulemd_packager_v3_set_summary (ModulemdPackagerV3 *self,
221 const gchar *summary)
222 {
223 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
224
225 g_clear_pointer (&self->summary, g_free);
226
227 if (summary)
228 {
229 self->summary = g_strdup (summary);
230 }
231 }
232
233
234 const gchar *
modulemd_packager_v3_get_summary(ModulemdPackagerV3 * self)235 modulemd_packager_v3_get_summary (ModulemdPackagerV3 *self)
236 {
237 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
238
239 return self->summary;
240 }
241
242
243 void
modulemd_packager_v3_set_description(ModulemdPackagerV3 * self,const gchar * description)244 modulemd_packager_v3_set_description (ModulemdPackagerV3 *self,
245 const gchar *description)
246 {
247 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
248
249 g_clear_pointer (&self->description, g_free);
250
251 if (description)
252 {
253 self->description = g_strdup (description);
254 }
255 }
256
257
258 const gchar *
modulemd_packager_v3_get_description(ModulemdPackagerV3 * self)259 modulemd_packager_v3_get_description (ModulemdPackagerV3 *self)
260 {
261 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
262
263 return self->description;
264 }
265
266
267 void
modulemd_packager_v3_add_module_license(ModulemdPackagerV3 * self,const gchar * license)268 modulemd_packager_v3_add_module_license (ModulemdPackagerV3 *self,
269 const gchar *license)
270 {
271 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
272
273 if (!license)
274 {
275 return;
276 }
277
278 g_hash_table_add (self->module_licenses, g_strdup (license));
279 }
280
281
282 void
modulemd_packager_v3_remove_module_license(ModulemdPackagerV3 * self,const gchar * license)283 modulemd_packager_v3_remove_module_license (ModulemdPackagerV3 *self,
284 const gchar *license)
285 {
286 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
287
288 if (!license)
289 {
290 return;
291 }
292
293 g_hash_table_remove (self->module_licenses, license);
294 }
295
296
297 void
modulemd_packager_v3_clear_module_licenses(ModulemdPackagerV3 * self)298 modulemd_packager_v3_clear_module_licenses (ModulemdPackagerV3 *self)
299 {
300 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
301
302 g_hash_table_remove_all (self->module_licenses);
303 }
304
305
306 GStrv
modulemd_packager_v3_get_module_licenses_as_strv(ModulemdPackagerV3 * self)307 modulemd_packager_v3_get_module_licenses_as_strv (ModulemdPackagerV3 *self)
308 {
309 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
310
311 return modulemd_ordered_str_keys_as_strv (self->module_licenses);
312 }
313
314
315 void
modulemd_packager_v3_set_xmd(ModulemdPackagerV3 * self,GVariant * xmd)316 modulemd_packager_v3_set_xmd (ModulemdPackagerV3 *self, GVariant *xmd)
317 {
318 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
319
320 /* Do nothing if we were passed the same pointer */
321 if (self->xmd == xmd)
322 {
323 return;
324 }
325
326 g_clear_pointer (&self->xmd, g_variant_unref);
327 self->xmd = modulemd_variant_deep_copy (xmd);
328 }
329
330 GVariant *
modulemd_packager_v3_get_xmd(ModulemdPackagerV3 * self)331 modulemd_packager_v3_get_xmd (ModulemdPackagerV3 *self)
332 {
333 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
334 return self->xmd;
335 }
336
337
338 guint64
modulemd_packager_v3_get_mdversion(ModulemdPackagerV3 * self)339 modulemd_packager_v3_get_mdversion (ModulemdPackagerV3 *self)
340 {
341 return MD_PACKAGER_VERSION_THREE;
342 }
343
344
345 void
modulemd_packager_v3_add_build_config(ModulemdPackagerV3 * self,ModulemdBuildConfig * buildconfig)346 modulemd_packager_v3_add_build_config (ModulemdPackagerV3 *self,
347 ModulemdBuildConfig *buildconfig)
348 {
349 if (!buildconfig)
350 return;
351
352 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
353 g_return_if_fail (MODULEMD_IS_BUILD_CONFIG (buildconfig));
354
355 g_hash_table_replace (
356 self->build_configs,
357 g_strdup (modulemd_build_config_get_context (buildconfig)),
358 modulemd_build_config_copy (buildconfig));
359 }
360
361
362 void
modulemd_packager_v3_clear_build_configs(ModulemdPackagerV3 * self)363 modulemd_packager_v3_clear_build_configs (ModulemdPackagerV3 *self)
364 {
365 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
366 g_hash_table_remove_all (self->build_configs);
367 }
368
369
370 GStrv
modulemd_packager_v3_get_build_config_contexts_as_strv(ModulemdPackagerV3 * self)371 modulemd_packager_v3_get_build_config_contexts_as_strv (
372 ModulemdPackagerV3 *self)
373 {
374 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
375
376 return modulemd_ordered_str_keys_as_strv (self->build_configs);
377 }
378
379
380 ModulemdBuildConfig *
modulemd_packager_v3_get_build_config(ModulemdPackagerV3 * self,const gchar * context)381 modulemd_packager_v3_get_build_config (ModulemdPackagerV3 *self,
382 const gchar *context)
383 {
384 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
385
386 return g_hash_table_lookup (self->build_configs, context);
387 }
388
389 void
modulemd_packager_v3_set_community(ModulemdPackagerV3 * self,const gchar * community)390 modulemd_packager_v3_set_community (ModulemdPackagerV3 *self,
391 const gchar *community)
392 {
393 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
394
395 g_clear_pointer (&self->community, g_free);
396
397 if (community)
398 {
399 self->community = g_strdup (community);
400 }
401 }
402
403
404 const gchar *
modulemd_packager_v3_get_community(ModulemdPackagerV3 * self)405 modulemd_packager_v3_get_community (ModulemdPackagerV3 *self)
406 {
407 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
408
409 return self->community;
410 }
411
412
413 void
modulemd_packager_v3_set_documentation(ModulemdPackagerV3 * self,const gchar * documentation)414 modulemd_packager_v3_set_documentation (ModulemdPackagerV3 *self,
415 const gchar *documentation)
416 {
417 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
418
419 g_clear_pointer (&self->documentation, g_free);
420
421 if (documentation)
422 {
423 self->documentation = g_strdup (documentation);
424 }
425 }
426
427
428 const gchar *
modulemd_packager_v3_get_documentation(ModulemdPackagerV3 * self)429 modulemd_packager_v3_get_documentation (ModulemdPackagerV3 *self)
430 {
431 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
432
433 return self->documentation;
434 }
435
436
437 void
modulemd_packager_v3_set_tracker(ModulemdPackagerV3 * self,const gchar * tracker)438 modulemd_packager_v3_set_tracker (ModulemdPackagerV3 *self,
439 const gchar *tracker)
440 {
441 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
442
443 g_clear_pointer (&self->tracker, g_free);
444
445 if (tracker)
446 {
447 self->tracker = g_strdup (tracker);
448 }
449 }
450
451
452 const gchar *
modulemd_packager_v3_get_tracker(ModulemdPackagerV3 * self)453 modulemd_packager_v3_get_tracker (ModulemdPackagerV3 *self)
454 {
455 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
456
457 return self->tracker;
458 }
459
460
461 void
modulemd_packager_v3_add_profile(ModulemdPackagerV3 * self,ModulemdProfile * profile)462 modulemd_packager_v3_add_profile (ModulemdPackagerV3 *self,
463 ModulemdProfile *profile)
464 {
465 if (!profile)
466 {
467 return;
468 }
469 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
470 g_return_if_fail (MODULEMD_IS_PROFILE (profile));
471
472 ModulemdProfile *copied_profile = modulemd_profile_copy (profile);
473
474 g_hash_table_replace (self->profiles,
475 g_strdup (modulemd_profile_get_name (profile)),
476 copied_profile);
477 }
478
479
480 void
modulemd_packager_v3_clear_profiles(ModulemdPackagerV3 * self)481 modulemd_packager_v3_clear_profiles (ModulemdPackagerV3 *self)
482 {
483 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
484
485 g_hash_table_remove_all (self->profiles);
486 }
487
488
489 GStrv
modulemd_packager_v3_get_profile_names_as_strv(ModulemdPackagerV3 * self)490 modulemd_packager_v3_get_profile_names_as_strv (ModulemdPackagerV3 *self)
491 {
492 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
493
494 return modulemd_ordered_str_keys_as_strv (self->profiles);
495 }
496
497
498 ModulemdProfile *
modulemd_packager_v3_get_profile(ModulemdPackagerV3 * self,const gchar * profile_name)499 modulemd_packager_v3_get_profile (ModulemdPackagerV3 *self,
500 const gchar *profile_name)
501 {
502 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
503
504 return g_hash_table_lookup (self->profiles, profile_name);
505 }
506
507
508 void
modulemd_packager_v3_add_rpm_api(ModulemdPackagerV3 * self,const gchar * rpm)509 modulemd_packager_v3_add_rpm_api (ModulemdPackagerV3 *self, const gchar *rpm)
510 {
511 if (!rpm)
512 {
513 return;
514 }
515
516 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
517
518 g_hash_table_add (self->rpm_api, g_strdup (rpm));
519 }
520
521
522 void
modulemd_packager_v3_replace_rpm_api(ModulemdPackagerV3 * self,GHashTable * set)523 modulemd_packager_v3_replace_rpm_api (ModulemdPackagerV3 *self,
524 GHashTable *set)
525 {
526 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
527
528 MODULEMD_REPLACE_SET (self->rpm_api, set);
529 }
530
531
532 void
modulemd_packager_v3_remove_rpm_api(ModulemdPackagerV3 * self,const gchar * rpm)533 modulemd_packager_v3_remove_rpm_api (ModulemdPackagerV3 *self,
534 const gchar *rpm)
535 {
536 if (!rpm)
537 {
538 return;
539 }
540
541 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
542
543 g_hash_table_remove (self->rpm_api, rpm);
544 }
545
546
547 void
modulemd_packager_v3_clear_rpm_api(ModulemdPackagerV3 * self)548 modulemd_packager_v3_clear_rpm_api (ModulemdPackagerV3 *self)
549 {
550 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
551
552 g_hash_table_remove_all (self->rpm_api);
553 }
554
555
556 GStrv
modulemd_packager_v3_get_rpm_api_as_strv(ModulemdPackagerV3 * self)557 modulemd_packager_v3_get_rpm_api_as_strv (ModulemdPackagerV3 *self)
558 {
559 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
560
561 return modulemd_ordered_str_keys_as_strv (self->rpm_api);
562 }
563
564 void
modulemd_packager_v3_add_rpm_filter(ModulemdPackagerV3 * self,const gchar * rpm)565 modulemd_packager_v3_add_rpm_filter (ModulemdPackagerV3 *self,
566 const gchar *rpm)
567 {
568 if (!rpm)
569 {
570 return;
571 }
572
573 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
574
575 g_hash_table_add (self->rpm_filters, g_strdup (rpm));
576 }
577
578
579 void
modulemd_packager_v3_replace_rpm_filters(ModulemdPackagerV3 * self,GHashTable * set)580 modulemd_packager_v3_replace_rpm_filters (ModulemdPackagerV3 *self,
581 GHashTable *set)
582 {
583 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
584
585 MODULEMD_REPLACE_SET (self->rpm_filters, set);
586 }
587
588
589 void
modulemd_packager_v3_remove_rpm_filter(ModulemdPackagerV3 * self,const gchar * rpm)590 modulemd_packager_v3_remove_rpm_filter (ModulemdPackagerV3 *self,
591 const gchar *rpm)
592 {
593 if (!rpm)
594 {
595 return;
596 }
597
598 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
599
600 g_hash_table_remove (self->rpm_filters, rpm);
601 }
602
603
604 void
modulemd_packager_v3_clear_rpm_filters(ModulemdPackagerV3 * self)605 modulemd_packager_v3_clear_rpm_filters (ModulemdPackagerV3 *self)
606 {
607 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
608
609 g_hash_table_remove_all (self->rpm_filters);
610 }
611
612
613 GStrv
modulemd_packager_v3_get_rpm_filters_as_strv(ModulemdPackagerV3 * self)614 modulemd_packager_v3_get_rpm_filters_as_strv (ModulemdPackagerV3 *self)
615 {
616 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
617
618 return modulemd_ordered_str_keys_as_strv (self->rpm_filters);
619 }
620
621
622 void
modulemd_packager_v3_add_demodularized_rpm(ModulemdPackagerV3 * self,const gchar * rpm)623 modulemd_packager_v3_add_demodularized_rpm (ModulemdPackagerV3 *self,
624 const gchar *rpm)
625 {
626 if (!rpm)
627 {
628 return;
629 }
630
631 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
632
633 g_hash_table_add (self->demodularized_rpms, g_strdup (rpm));
634 }
635
636
637 void
modulemd_packager_v3_replace_demodularized_rpms(ModulemdPackagerV3 * self,GHashTable * set)638 modulemd_packager_v3_replace_demodularized_rpms (ModulemdPackagerV3 *self,
639 GHashTable *set)
640 {
641 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
642
643 MODULEMD_REPLACE_SET (self->demodularized_rpms, set);
644 }
645
646
647 void
modulemd_packager_v3_remove_demodularized_rpm(ModulemdPackagerV3 * self,const gchar * rpm)648 modulemd_packager_v3_remove_demodularized_rpm (ModulemdPackagerV3 *self,
649 const gchar *rpm)
650 {
651 if (!rpm)
652 {
653 return;
654 }
655
656 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
657
658 g_hash_table_remove (self->demodularized_rpms, rpm);
659 }
660
661
662 void
modulemd_packager_v3_clear_demodularized_rpms(ModulemdPackagerV3 * self)663 modulemd_packager_v3_clear_demodularized_rpms (ModulemdPackagerV3 *self)
664 {
665 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
666
667 g_hash_table_remove_all (self->demodularized_rpms);
668 }
669
670
671 GStrv
modulemd_packager_v3_get_demodularized_rpms(ModulemdPackagerV3 * self)672 modulemd_packager_v3_get_demodularized_rpms (ModulemdPackagerV3 *self)
673 {
674 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
675
676 return modulemd_ordered_str_keys_as_strv (self->demodularized_rpms);
677 }
678
679
680 void
modulemd_packager_v3_add_component(ModulemdPackagerV3 * self,ModulemdComponent * component)681 modulemd_packager_v3_add_component (ModulemdPackagerV3 *self,
682 ModulemdComponent *component)
683 {
684 GHashTable *table = NULL;
685
686 /* Do nothing if we were passed a NULL component */
687 if (!component)
688 {
689 return;
690 }
691
692 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
693 g_return_if_fail (MODULEMD_IS_COMPONENT (component));
694
695 if (MODULEMD_IS_COMPONENT_RPM (component))
696 {
697 table = self->rpm_components;
698 }
699 else if (MODULEMD_IS_COMPONENT_MODULE (component))
700 {
701 table = self->module_components;
702 }
703 else
704 {
705 /* Unknown component. Raise a warning and return */
706 g_return_if_reached ();
707 }
708
709 /* Add the component to the table. This will replace an existing component
710 * with the same name
711 */
712 g_hash_table_replace (table,
713 g_strdup (modulemd_component_get_key (component)),
714 modulemd_component_copy (component, NULL));
715 }
716
717
718 void
modulemd_packager_v3_remove_module_component(ModulemdPackagerV3 * self,const gchar * component_name)719 modulemd_packager_v3_remove_module_component (ModulemdPackagerV3 *self,
720 const gchar *component_name)
721 {
722 /* Do nothing if we were passed a NULL component_name */
723 if (!component_name)
724 {
725 return;
726 }
727
728 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
729
730 g_hash_table_remove (self->module_components, component_name);
731 }
732
733
734 void
modulemd_packager_v3_clear_module_components(ModulemdPackagerV3 * self)735 modulemd_packager_v3_clear_module_components (ModulemdPackagerV3 *self)
736 {
737 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
738
739 g_hash_table_remove_all (self->module_components);
740 }
741
742
743 void
modulemd_packager_v3_remove_rpm_component(ModulemdPackagerV3 * self,const gchar * component_name)744 modulemd_packager_v3_remove_rpm_component (ModulemdPackagerV3 *self,
745 const gchar *component_name)
746 {
747 /* Do nothing if we were passed a NULL component_name */
748 if (!component_name)
749 {
750 return;
751 }
752
753 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
754
755 g_hash_table_remove (self->rpm_components, component_name);
756 }
757
758
759 void
modulemd_packager_v3_clear_rpm_components(ModulemdPackagerV3 * self)760 modulemd_packager_v3_clear_rpm_components (ModulemdPackagerV3 *self)
761 {
762 g_return_if_fail (MODULEMD_IS_PACKAGER_V3 (self));
763
764 g_hash_table_remove_all (self->rpm_components);
765 }
766
767
768 GStrv
modulemd_packager_v3_get_module_component_names_as_strv(ModulemdPackagerV3 * self)769 modulemd_packager_v3_get_module_component_names_as_strv (
770 ModulemdPackagerV3 *self)
771 {
772 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
773
774 return modulemd_ordered_str_keys_as_strv (self->module_components);
775 }
776
777
778 GStrv
modulemd_packager_v3_get_rpm_component_names_as_strv(ModulemdPackagerV3 * self)779 modulemd_packager_v3_get_rpm_component_names_as_strv (ModulemdPackagerV3 *self)
780 {
781 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
782
783 return modulemd_ordered_str_keys_as_strv (self->rpm_components);
784 }
785
786
787 ModulemdComponentModule *
modulemd_packager_v3_get_module_component(ModulemdPackagerV3 * self,const gchar * component_name)788 modulemd_packager_v3_get_module_component (ModulemdPackagerV3 *self,
789 const gchar *component_name)
790 {
791 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
792
793 return g_hash_table_lookup (self->module_components, component_name);
794 }
795
796
797 ModulemdComponentRpm *
modulemd_packager_v3_get_rpm_component(ModulemdPackagerV3 * self,const gchar * component_name)798 modulemd_packager_v3_get_rpm_component (ModulemdPackagerV3 *self,
799 const gchar *component_name)
800 {
801 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
802
803 return g_hash_table_lookup (self->rpm_components, component_name);
804 }
805
806
807 gboolean
modulemd_packager_v3_to_defaults(ModulemdPackagerV3 * self,ModulemdDefaults ** defaults_ptr,GError ** error)808 modulemd_packager_v3_to_defaults (ModulemdPackagerV3 *self,
809 ModulemdDefaults **defaults_ptr,
810 GError **error)
811 {
812 g_autoptr (ModulemdDefaultsV1) defaults = NULL;
813 ModulemdProfile *profile;
814 g_autoptr (GError) nested_error = NULL;
815 GHashTableIter iter;
816 gpointer value;
817
818 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
819 g_return_val_if_fail (defaults_ptr == NULL || *defaults_ptr == NULL, FALSE);
820 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), FALSE);
821
822 g_hash_table_iter_init (&iter, self->profiles);
823 while (g_hash_table_iter_next (&iter, NULL, &value))
824 {
825 profile = MODULEMD_PROFILE (value);
826 if (modulemd_profile_is_default (profile))
827 {
828 if (!defaults)
829 {
830 defaults = modulemd_defaults_v1_new (self->module_name);
831 }
832 modulemd_defaults_v1_add_default_profile_for_stream (
833 defaults,
834 self->stream_name,
835 modulemd_profile_get_name (profile),
836 NULL);
837 }
838 }
839
840 if (!defaults)
841 {
842 return TRUE;
843 }
844
845 if (!modulemd_defaults_validate (MODULEMD_DEFAULTS (defaults),
846 &nested_error))
847 {
848 g_propagate_error (error, g_steal_pointer (&nested_error));
849 return FALSE;
850 }
851
852 *defaults_ptr = MODULEMD_DEFAULTS (g_steal_pointer (&defaults));
853 return TRUE;
854 }
855
856
857 static void
copy_packager_v3_common_to_stream_v2(ModulemdModuleStreamV2 * stream_v2,ModulemdPackagerV3 * packager_v3)858 copy_packager_v3_common_to_stream_v2 (ModulemdModuleStreamV2 *stream_v2,
859 ModulemdPackagerV3 *packager_v3)
860 {
861 g_autoptr (ModulemdProfile) profile = NULL;
862 GHashTableIter iter;
863 gpointer value;
864
865 modulemd_module_stream_v2_set_summary (
866 stream_v2, modulemd_packager_v3_get_summary (packager_v3));
867
868 modulemd_module_stream_v2_set_description (
869 stream_v2, modulemd_packager_v3_get_description (packager_v3));
870
871 /* Packager v3 "license" is optional. Stream v2 "license" is required
872 * Fill in the default Packager v3 license if none has been specified.
873 */
874 if (g_hash_table_size (packager_v3->module_licenses) == 0)
875 {
876 modulemd_module_stream_v2_add_module_license (
877 stream_v2, MMD_PACKAGER_DEFAULT_MODULE_LICENSE);
878 }
879 else
880 {
881 MODULEMD_REPLACE_SET (stream_v2->module_licenses,
882 packager_v3->module_licenses);
883 }
884
885 modulemd_module_stream_v2_set_xmd (
886 stream_v2, modulemd_packager_v3_get_xmd (packager_v3));
887
888 modulemd_module_stream_v2_set_community (
889 stream_v2, modulemd_packager_v3_get_community (packager_v3));
890
891 modulemd_module_stream_v2_set_documentation (
892 stream_v2, modulemd_packager_v3_get_documentation (packager_v3));
893
894 modulemd_module_stream_v2_set_tracker (
895 stream_v2, modulemd_packager_v3_get_tracker (packager_v3));
896
897 g_hash_table_iter_init (&iter, packager_v3->profiles);
898 while (g_hash_table_iter_next (&iter, NULL, &value))
899 {
900 profile = modulemd_profile_copy (MODULEMD_PROFILE (value));
901 modulemd_profile_unset_default (profile);
902 modulemd_module_stream_v2_add_profile (stream_v2, profile);
903 g_clear_object (&profile);
904 }
905
906 modulemd_module_stream_v2_replace_rpm_api (stream_v2, packager_v3->rpm_api);
907
908 modulemd_module_stream_v2_replace_rpm_filters (stream_v2,
909 packager_v3->rpm_filters);
910
911 modulemd_module_stream_v2_replace_demodularized_rpms (
912 stream_v2, packager_v3->demodularized_rpms);
913
914 COPY_HASHTABLE_BY_VALUE_ADDER (stream_v2,
915 packager_v3,
916 rpm_components,
917 modulemd_module_stream_v2_add_component);
918
919 COPY_HASHTABLE_BY_VALUE_ADDER (stream_v2,
920 packager_v3,
921 module_components,
922 modulemd_module_stream_v2_add_component);
923 }
924
925 static void
copy_packager_v3_buildconfig_to_stream_v2(ModulemdModuleStreamV2 * stream_v2,ModulemdBuildConfig * bc)926 copy_packager_v3_buildconfig_to_stream_v2 (ModulemdModuleStreamV2 *stream_v2,
927 ModulemdBuildConfig *bc)
928 {
929 g_autoptr (ModulemdDependencies) deps = NULL;
930 g_auto (GStrv) modules = NULL;
931
932 modulemd_module_stream_v2_set_buildopts (
933 stream_v2, modulemd_build_config_get_buildopts (bc));
934
935 deps = modulemd_dependencies_new ();
936
937 modulemd_dependencies_add_buildtime_stream (
938 deps, "platform", modulemd_build_config_get_platform (bc));
939 modulemd_dependencies_add_runtime_stream (
940 deps, "platform", modulemd_build_config_get_platform (bc));
941
942 modules = modulemd_build_config_get_buildtime_modules_as_strv (bc);
943 for (guint j = 0; j < g_strv_length (modules); j++)
944 {
945 modulemd_dependencies_add_buildtime_stream (
946 deps,
947 modules[j],
948 modulemd_build_config_get_buildtime_requirement_stream (bc,
949 modules[j]));
950 }
951 g_clear_pointer (&modules, g_strfreev);
952
953 modules = modulemd_build_config_get_runtime_modules_as_strv (bc);
954 for (guint j = 0; j < g_strv_length (modules); j++)
955 {
956 modulemd_dependencies_add_runtime_stream (
957 deps,
958 modules[j],
959 modulemd_build_config_get_runtime_requirement_stream (bc, modules[j]));
960 }
961 g_clear_pointer (&modules, g_strfreev);
962
963 modulemd_module_stream_v2_add_dependencies (stream_v2, deps);
964 g_clear_object (&deps);
965 }
966
967
968 ModulemdModuleStreamV2 *
modulemd_packager_v3_to_stream_v2(ModulemdPackagerV3 * self,GError ** error)969 modulemd_packager_v3_to_stream_v2 (ModulemdPackagerV3 *self, GError **error)
970 {
971 g_autoptr (ModulemdModuleStreamV2) v2_stream = NULL;
972 g_auto (GStrv) contexts = NULL;
973 g_autoptr (GError) nested_error = NULL;
974 ModulemdBuildopts *buildopts = NULL;
975 ModulemdBuildConfig *bc;
976
977 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
978 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
979
980 v2_stream = modulemd_module_stream_v2_new (
981 modulemd_packager_v3_get_module_name (self),
982 modulemd_packager_v3_get_stream_name (self));
983
984 /* set attributes that are the same for all streams */
985 copy_packager_v3_common_to_stream_v2 (v2_stream, self);
986
987 /* get the list of packager build configuration contexts */
988 contexts = modulemd_packager_v3_get_build_config_contexts_as_strv (self);
989
990 /* If there is exactly one build configuration, use it for the stream */
991 /* context. Otherwise, leave the stream context unset. */
992 if (g_strv_length (contexts) == 1)
993 {
994 modulemd_module_stream_set_context (MODULEMD_MODULE_STREAM (v2_stream),
995 contexts[0]);
996 }
997
998 /* map each BuildConfig object to a Dependencies object within the same StreamV2 object */
999 for (guint i = 0; i < g_strv_length (contexts); i++)
1000 {
1001 bc = modulemd_packager_v3_get_build_config (self, contexts[i]);
1002
1003 if (i == 0)
1004 {
1005 /* Save the buildopts from the first build configuration to */
1006 /* set the stream buildopts. */
1007 buildopts = modulemd_build_config_get_buildopts (bc);
1008 }
1009
1010 /* set attributes that are unique per build configuration */
1011 copy_packager_v3_buildconfig_to_stream_v2 (v2_stream, bc);
1012 }
1013 g_clear_pointer (&contexts, g_strfreev);
1014
1015 /* set the saved buildopts from the first build configuration */
1016 modulemd_module_stream_v2_set_buildopts (v2_stream, buildopts);
1017
1018 if (!modulemd_module_stream_validate (MODULEMD_MODULE_STREAM (v2_stream),
1019 &nested_error))
1020 {
1021 g_propagate_error (error, g_steal_pointer (&nested_error));
1022 return NULL;
1023 }
1024
1025 return g_steal_pointer (&v2_stream);
1026 }
1027
1028 ModulemdModuleIndex *
modulemd_packager_v3_to_stream_v2_ext(ModulemdPackagerV3 * self,GError ** error)1029 modulemd_packager_v3_to_stream_v2_ext (ModulemdPackagerV3 *self,
1030 GError **error)
1031 {
1032 g_autoptr (ModulemdModuleIndex) index = NULL;
1033 g_autoptr (ModulemdModuleStreamV2) v2_stream = NULL;
1034 g_autoptr (ModulemdDefaults) defaults = NULL;
1035 g_autoptr (GError) nested_error = NULL;
1036
1037 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1038 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
1039
1040 v2_stream = modulemd_packager_v3_to_stream_v2 (self, &nested_error);
1041 if (!v2_stream)
1042 {
1043 g_propagate_error (error, g_steal_pointer (&nested_error));
1044 return NULL;
1045 }
1046
1047 /* autogen module/stream names if necessary for adding to index */
1048
1049 modulemd_module_stream_set_autogen_module_name (
1050 MODULEMD_MODULE_STREAM (v2_stream), 0);
1051 modulemd_module_stream_set_autogen_stream_name (
1052 MODULEMD_MODULE_STREAM (v2_stream), 0);
1053
1054 index = modulemd_module_index_new ();
1055 if (!modulemd_module_index_add_module_stream (
1056 index, MODULEMD_MODULE_STREAM (v2_stream), &nested_error))
1057 {
1058 g_propagate_error (error, g_steal_pointer (&nested_error));
1059 return NULL;
1060 }
1061
1062 g_clear_object (&v2_stream);
1063
1064 if (!modulemd_packager_v3_to_defaults (self, &defaults, &nested_error))
1065 {
1066 g_propagate_error (error, g_steal_pointer (&nested_error));
1067 return NULL;
1068 }
1069
1070 if (defaults)
1071 {
1072 if (!modulemd_module_index_add_defaults (index, defaults, &nested_error))
1073 {
1074 g_propagate_error (error, g_steal_pointer (&nested_error));
1075 return NULL;
1076 }
1077
1078 g_clear_object (&defaults);
1079 }
1080
1081 return g_steal_pointer (&index);
1082 }
1083
1084
1085 ModulemdModuleIndex *
modulemd_packager_v3_convert_to_index(ModulemdPackagerV3 * self,GError ** error)1086 modulemd_packager_v3_convert_to_index (ModulemdPackagerV3 *self,
1087 GError **error)
1088 {
1089 g_auto (GStrv) contexts = NULL;
1090 g_autoptr (ModulemdModuleIndex) index = NULL;
1091 g_autoptr (ModulemdModuleStreamV2) v2_stream = NULL;
1092 g_autoptr (ModulemdDefaults) defaults = NULL;
1093 g_autoptr (GError) nested_error = NULL;
1094 ModulemdBuildConfig *bc;
1095
1096 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1097 g_return_val_if_fail (MODULEMD_IS_PACKAGER_V3 (self), NULL);
1098
1099 /* get the list of packager build configuration contexts */
1100 contexts = modulemd_packager_v3_get_build_config_contexts_as_strv (self);
1101
1102 if (g_strv_length (contexts) == 0)
1103 {
1104 g_set_error_literal (error,
1105 MODULEMD_ERROR,
1106 MMD_ERROR_VALIDATE,
1107 "Packager document with no build configurations "
1108 "cannot be converted to stream");
1109 return NULL;
1110 }
1111
1112 /* create a ModuleIndex to contain the results */
1113 index = modulemd_module_index_new ();
1114
1115 /* create a StreamV2 object for each BuildConfig object */
1116 for (guint i = 0; i < g_strv_length (contexts); i++)
1117 {
1118 bc = modulemd_packager_v3_get_build_config (self, contexts[i]);
1119
1120 v2_stream = modulemd_module_stream_v2_new (
1121 modulemd_packager_v3_get_module_name (self),
1122 modulemd_packager_v3_get_stream_name (self));
1123
1124 modulemd_module_stream_set_context (MODULEMD_MODULE_STREAM (v2_stream),
1125 contexts[i]);
1126
1127 /* set attributes that are the same for all streams */
1128 copy_packager_v3_common_to_stream_v2 (v2_stream, self);
1129
1130 /* set attributes that are unique per build configuration */
1131 copy_packager_v3_buildconfig_to_stream_v2 (v2_stream, bc);
1132
1133 if (!modulemd_module_stream_validate (MODULEMD_MODULE_STREAM (v2_stream),
1134 &nested_error))
1135 {
1136 g_propagate_error (error, g_steal_pointer (&nested_error));
1137 return NULL;
1138 }
1139
1140 /* autogen module/stream names if necessary for adding to index */
1141
1142 modulemd_module_stream_set_autogen_module_name (
1143 MODULEMD_MODULE_STREAM (v2_stream), 0);
1144 modulemd_module_stream_set_autogen_stream_name (
1145 MODULEMD_MODULE_STREAM (v2_stream), 0);
1146
1147 if (!modulemd_module_index_add_module_stream (
1148 index, MODULEMD_MODULE_STREAM (v2_stream), &nested_error))
1149 {
1150 g_propagate_error (error, g_steal_pointer (&nested_error));
1151 return NULL;
1152 }
1153
1154 g_clear_object (&v2_stream);
1155 }
1156 g_clear_pointer (&contexts, g_strfreev);
1157
1158 if (!modulemd_packager_v3_to_defaults (self, &defaults, &nested_error))
1159 {
1160 g_propagate_error (error, g_steal_pointer (&nested_error));
1161 return NULL;
1162 }
1163
1164 if (defaults)
1165 {
1166 if (!modulemd_module_index_add_defaults (index, defaults, &nested_error))
1167 {
1168 g_propagate_error (error, g_steal_pointer (&nested_error));
1169 return NULL;
1170 }
1171
1172 g_clear_object (&defaults);
1173 }
1174
1175 return g_steal_pointer (&index);
1176 }
1177
1178
1179 static gboolean
1180 modulemd_packager_v3_parse_build_configs (yaml_parser_t *parser,
1181 ModulemdPackagerV3 *packager,
1182 gboolean strict,
1183 GError **error);
1184
1185 static gboolean
1186 modulemd_packager_v3_parse_refs (yaml_parser_t *parser,
1187 ModulemdPackagerV3 *packager,
1188 gboolean strict,
1189 GError **error);
1190
1191 static gboolean
1192 modulemd_packager_v3_parse_profiles (yaml_parser_t *parser,
1193 ModulemdPackagerV3 *packager,
1194 gboolean strict,
1195 GError **error);
1196
1197 static gboolean
1198 modulemd_packager_v3_parse_components (yaml_parser_t *parser,
1199 ModulemdPackagerV3 *packager,
1200 gboolean strict,
1201 GError **error);
1202
1203
1204 ModulemdPackagerV3 *
modulemd_packager_v3_parse_yaml(ModulemdSubdocumentInfo * subdoc,GError ** error)1205 modulemd_packager_v3_parse_yaml (ModulemdSubdocumentInfo *subdoc,
1206 GError **error)
1207 {
1208 MODULEMD_INIT_TRACE ();
1209 MMD_INIT_YAML_PARSER (parser);
1210 MMD_INIT_YAML_EVENT (event);
1211 gboolean done = FALSE;
1212 const gboolean strict = TRUE; /* PackagerV3 should always parse strictly */
1213 g_autoptr (GError) nested_error = NULL;
1214 g_autoptr (ModulemdPackagerV3) packager = NULL;
1215 g_autoptr (GHashTable) set = NULL;
1216 g_autoptr (GVariant) xmd = NULL;
1217
1218 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1219
1220 if (!modulemd_subdocument_info_get_data_parser (
1221 subdoc, &parser, strict, error))
1222 {
1223 return FALSE;
1224 }
1225
1226 packager = modulemd_packager_v3_new ();
1227
1228 /* Read the MAPPING_START */
1229 YAML_PARSER_PARSE_WITH_EXIT (&parser, &event, error);
1230 if (event.type != YAML_MAPPING_START_EVENT)
1231 {
1232 MMD_YAML_ERROR_EVENT_EXIT (
1233 error, event, "Data section did not begin with a map.");
1234 }
1235
1236 /* Process through the mapping */
1237 while (!done)
1238 {
1239 YAML_PARSER_PARSE_WITH_EXIT (&parser, &event, error);
1240
1241 switch (event.type)
1242 {
1243 case YAML_MAPPING_END_EVENT: done = TRUE; break;
1244
1245 case YAML_SCALAR_EVENT:
1246 /* Mapping Keys */
1247 if (g_str_equal ((const gchar *)event.data.scalar.value, "name"))
1248 {
1249 MMD_SET_PARSED_YAML_STRING (&parser,
1250 error,
1251 modulemd_packager_v3_set_module_name,
1252 packager);
1253 }
1254
1255 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1256 "stream"))
1257 {
1258 MMD_SET_PARSED_YAML_STRING (&parser,
1259 error,
1260 modulemd_packager_v3_set_stream_name,
1261 packager);
1262 }
1263
1264 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1265 "summary"))
1266 {
1267 MMD_SET_PARSED_YAML_STRING (
1268 &parser, error, modulemd_packager_v3_set_summary, packager);
1269 }
1270
1271 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1272 "description"))
1273 {
1274 MMD_SET_PARSED_YAML_STRING (&parser,
1275 error,
1276 modulemd_packager_v3_set_description,
1277 packager);
1278 }
1279
1280 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1281 "license"))
1282 {
1283 set = modulemd_yaml_parse_string_set (&parser, &nested_error);
1284 MODULEMD_REPLACE_SET (packager->module_licenses, set);
1285 g_clear_pointer (&set, g_hash_table_unref);
1286 }
1287
1288 else if (g_str_equal ((const gchar *)event.data.scalar.value, "xmd"))
1289 {
1290 xmd = mmd_parse_xmd (&parser, &nested_error);
1291 if (!xmd)
1292 {
1293 g_propagate_error (error, g_steal_pointer (&nested_error));
1294 return NULL;
1295 }
1296 modulemd_packager_v3_set_xmd (packager, xmd);
1297 g_clear_pointer (&xmd, g_variant_unref);
1298 }
1299
1300 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1301 "configurations"))
1302 {
1303 if (!modulemd_packager_v3_parse_build_configs (
1304 &parser, packager, strict, &nested_error))
1305 {
1306 g_propagate_error (error, g_steal_pointer (&nested_error));
1307 return NULL;
1308 }
1309 }
1310
1311 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1312 "references"))
1313 {
1314 if (!modulemd_packager_v3_parse_refs (
1315 &parser, packager, strict, &nested_error))
1316 {
1317 g_propagate_error (error, g_steal_pointer (&nested_error));
1318 return NULL;
1319 }
1320 }
1321
1322 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1323 "profiles"))
1324 {
1325 if (!modulemd_packager_v3_parse_profiles (
1326 &parser, packager, strict, &nested_error))
1327 {
1328 g_propagate_error (error, g_steal_pointer (&nested_error));
1329 return NULL;
1330 }
1331 }
1332
1333 else if (g_str_equal ((const gchar *)event.data.scalar.value, "api"))
1334 {
1335 set = modulemd_yaml_parse_string_set_from_map (
1336 &parser, "rpms", strict, &nested_error);
1337 modulemd_packager_v3_replace_rpm_api (packager, set);
1338 g_clear_pointer (&set, g_hash_table_unref);
1339 }
1340
1341 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1342 "filter"))
1343 {
1344 set = modulemd_yaml_parse_string_set_from_map (
1345 &parser, "rpms", strict, &nested_error);
1346 modulemd_packager_v3_replace_rpm_filters (packager, set);
1347 g_clear_pointer (&set, g_hash_table_unref);
1348 }
1349
1350 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1351 "demodularized"))
1352 {
1353 set = modulemd_yaml_parse_string_set_from_map (
1354 &parser, "rpms", strict, &nested_error);
1355 modulemd_packager_v3_replace_demodularized_rpms (packager, set);
1356 g_clear_pointer (&set, g_hash_table_unref);
1357 }
1358
1359 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1360 "components"))
1361 {
1362 if (!modulemd_packager_v3_parse_components (
1363 &parser, packager, strict, &nested_error))
1364 {
1365 g_propagate_error (error, g_steal_pointer (&nested_error));
1366 return NULL;
1367 }
1368 }
1369
1370 else
1371 {
1372 SKIP_UNKNOWN (&parser,
1373 NULL,
1374 "Unexpected key in packager v3 document: %s",
1375 (const gchar *)event.data.scalar.value);
1376 break;
1377 }
1378
1379 break;
1380
1381 default:
1382 MMD_YAML_ERROR_EVENT_EXIT (
1383 error,
1384 event,
1385 "Unexpected YAML event in ModuleStreamV2: %s",
1386 mmd_yaml_get_event_name (event.type));
1387 break;
1388 }
1389 yaml_event_delete (&event);
1390 }
1391
1392 return g_steal_pointer (&packager);
1393 }
1394
1395
1396 static gboolean
modulemd_packager_v3_parse_build_configs(yaml_parser_t * parser,ModulemdPackagerV3 * packager,gboolean strict,GError ** error)1397 modulemd_packager_v3_parse_build_configs (yaml_parser_t *parser,
1398 ModulemdPackagerV3 *packager,
1399 gboolean strict,
1400 GError **error)
1401 {
1402 MMD_INIT_YAML_EVENT (event);
1403 gboolean done = FALSE;
1404 g_autoptr (ModulemdBuildConfig) buildconfig = NULL;
1405 g_autoptr (GError) nested_error = NULL;
1406
1407 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
1408 if (event.type != YAML_SEQUENCE_START_EVENT)
1409 {
1410 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1411 error, event, "Unexpected YAML event in build_configs");
1412 }
1413
1414 while (!done)
1415 {
1416 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
1417
1418 switch (event.type)
1419 {
1420 case YAML_SEQUENCE_END_EVENT: done = TRUE; break;
1421
1422 case YAML_MAPPING_START_EVENT:
1423 buildconfig =
1424 modulemd_build_config_parse_yaml (parser, strict, &nested_error);
1425 if (!buildconfig)
1426 {
1427 g_propagate_error (error, g_steal_pointer (&nested_error));
1428 return FALSE;
1429 }
1430 modulemd_packager_v3_add_build_config (packager, buildconfig);
1431 g_clear_object (&buildconfig);
1432 break;
1433
1434 default:
1435 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1436 error, event, "Unexpected YAML event in build_config list");
1437 break;
1438 }
1439 yaml_event_delete (&event);
1440 }
1441
1442 return TRUE;
1443 }
1444
1445
1446 static gboolean
modulemd_packager_v3_parse_refs(yaml_parser_t * parser,ModulemdPackagerV3 * packager,gboolean strict,GError ** error)1447 modulemd_packager_v3_parse_refs (yaml_parser_t *parser,
1448 ModulemdPackagerV3 *packager,
1449 gboolean strict,
1450 GError **error)
1451 {
1452 MODULEMD_INIT_TRACE ();
1453 MMD_INIT_YAML_EVENT (event);
1454 gboolean done = FALSE;
1455 g_autofree gchar *scalar = NULL;
1456 g_autoptr (GError) nested_error = NULL;
1457
1458 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1459
1460 /* Process through the map */
1461 /* We *must* get a MAPPING_START here */
1462 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
1463 if (event.type != YAML_MAPPING_START_EVENT)
1464 {
1465 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1466 error,
1467 event,
1468 "Got %s instead of MAPPING_START in references.",
1469 mmd_yaml_get_event_name (event.type));
1470 }
1471
1472 while (!done)
1473 {
1474 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
1475
1476 switch (event.type)
1477 {
1478 case YAML_MAPPING_END_EVENT: done = TRUE; break;
1479
1480 case YAML_SCALAR_EVENT:
1481 if (g_str_equal ((const gchar *)event.data.scalar.value,
1482 "community"))
1483 {
1484 scalar = modulemd_yaml_parse_string (parser, &nested_error);
1485 if (!scalar)
1486 {
1487 g_propagate_error (error, g_steal_pointer (&nested_error));
1488 return FALSE;
1489 }
1490
1491 modulemd_packager_v3_set_community (packager, scalar);
1492 g_clear_pointer (&scalar, g_free);
1493 }
1494
1495 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1496 "documentation"))
1497 {
1498 scalar = modulemd_yaml_parse_string (parser, &nested_error);
1499 if (!scalar)
1500 {
1501 g_propagate_error (error, g_steal_pointer (&nested_error));
1502 return FALSE;
1503 }
1504
1505 modulemd_packager_v3_set_documentation (packager, scalar);
1506 g_clear_pointer (&scalar, g_free);
1507 }
1508
1509 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1510 "tracker"))
1511 {
1512 scalar = modulemd_yaml_parse_string (parser, &nested_error);
1513 if (!scalar)
1514 {
1515 g_propagate_error (error, g_steal_pointer (&nested_error));
1516 return FALSE;
1517 }
1518
1519 modulemd_packager_v3_set_tracker (packager, scalar);
1520 g_clear_pointer (&scalar, g_free);
1521 }
1522
1523 else
1524 {
1525 SKIP_UNKNOWN (parser,
1526 FALSE,
1527 "Unexpected key in references: %s",
1528 (const gchar *)event.data.scalar.value);
1529 break;
1530 }
1531 break;
1532
1533 default:
1534 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1535 error,
1536 event,
1537 "Unexpected YAML event in references: %s",
1538 mmd_yaml_get_event_name (event.type));
1539 break;
1540 }
1541 yaml_event_delete (&event);
1542 }
1543
1544 return TRUE;
1545 }
1546
1547
1548 static gboolean
modulemd_packager_v3_parse_profiles(yaml_parser_t * parser,ModulemdPackagerV3 * packager,gboolean strict,GError ** error)1549 modulemd_packager_v3_parse_profiles (yaml_parser_t *parser,
1550 ModulemdPackagerV3 *packager,
1551 gboolean strict,
1552 GError **error)
1553 {
1554 MODULEMD_INIT_TRACE ();
1555 MMD_INIT_YAML_EVENT (event);
1556 gboolean done = FALSE;
1557 g_autoptr (GError) nested_error = NULL;
1558 g_autoptr (ModulemdProfile) profile = NULL;
1559
1560 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1561
1562 /* Process through the map */
1563 /* We *must* get a MAPPING_START here */
1564 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
1565 if (event.type != YAML_MAPPING_START_EVENT)
1566 {
1567 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1568 error,
1569 event,
1570 "Got %s instead of MAPPING_START in profiles.",
1571 mmd_yaml_get_event_name (event.type));
1572 }
1573
1574 while (!done)
1575 {
1576 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
1577
1578 switch (event.type)
1579 {
1580 case YAML_MAPPING_END_EVENT: done = TRUE; break;
1581
1582 case YAML_SCALAR_EVENT:
1583 profile = modulemd_profile_parse_yaml (
1584 parser,
1585 (const gchar *)event.data.scalar.value,
1586 strict,
1587 &nested_error);
1588 if (!profile)
1589 {
1590 g_propagate_error (error, g_steal_pointer (&nested_error));
1591 return FALSE;
1592 }
1593
1594 modulemd_packager_v3_add_profile (packager, profile);
1595 g_clear_pointer (&profile, g_object_unref);
1596 break;
1597
1598 default:
1599 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1600 error,
1601 event,
1602 "Unexpected YAML event in profiles: %s",
1603 mmd_yaml_get_event_name (event.type));
1604 break;
1605 }
1606 yaml_event_delete (&event);
1607 }
1608
1609 return TRUE;
1610 }
1611
1612
1613 static gboolean
1614 modulemd_packager_v3_parse_rpm_components (yaml_parser_t *parser,
1615 ModulemdPackagerV3 *packager,
1616 gboolean strict,
1617 GError **error);
1618 static gboolean
1619 modulemd_packager_v3_parse_module_components (yaml_parser_t *parser,
1620 ModulemdPackagerV3 *packager,
1621 gboolean strict,
1622 GError **error);
1623
1624
1625 static gboolean
modulemd_packager_v3_parse_components(yaml_parser_t * parser,ModulemdPackagerV3 * packager,gboolean strict,GError ** error)1626 modulemd_packager_v3_parse_components (yaml_parser_t *parser,
1627 ModulemdPackagerV3 *packager,
1628 gboolean strict,
1629 GError **error)
1630 {
1631 MODULEMD_INIT_TRACE ();
1632 MMD_INIT_YAML_EVENT (event);
1633 gboolean done = FALSE;
1634 g_autoptr (GError) nested_error = NULL;
1635
1636 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1637
1638 /* Process through the sequence */
1639 /* We *must* get a MAPPING_START here */
1640 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
1641 if (event.type != YAML_MAPPING_START_EVENT)
1642 {
1643 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1644 error,
1645 event,
1646 "Got %s instead of MAPPING_START in components.",
1647 mmd_yaml_get_event_name (event.type));
1648 }
1649
1650 while (!done)
1651 {
1652 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
1653
1654 switch (event.type)
1655 {
1656 case YAML_MAPPING_END_EVENT: done = TRUE; break;
1657
1658 case YAML_SCALAR_EVENT:
1659 if (g_str_equal ((const gchar *)event.data.scalar.value, "rpms"))
1660 {
1661 if (!modulemd_packager_v3_parse_rpm_components (
1662 parser, packager, strict, &nested_error))
1663 {
1664 g_propagate_error (error, g_steal_pointer (&nested_error));
1665 return FALSE;
1666 }
1667 }
1668
1669 else if (g_str_equal ((const gchar *)event.data.scalar.value,
1670 "modules"))
1671 {
1672 if (!modulemd_packager_v3_parse_module_components (
1673 parser, packager, strict, &nested_error))
1674 {
1675 g_propagate_error (error, g_steal_pointer (&nested_error));
1676 return FALSE;
1677 }
1678 }
1679
1680 else
1681 {
1682 SKIP_UNKNOWN (parser,
1683 FALSE,
1684 "Unexpected key in components: %s",
1685 (const gchar *)event.data.scalar.value);
1686 }
1687
1688 break;
1689
1690
1691 default:
1692 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1693 error,
1694 event,
1695 "Unexpected YAML event in components: %s",
1696 mmd_yaml_get_event_name (event.type));
1697 break;
1698 }
1699 yaml_event_delete (&event);
1700 }
1701
1702 return TRUE;
1703 }
1704
1705
1706 static gboolean
modulemd_packager_v3_parse_rpm_components(yaml_parser_t * parser,ModulemdPackagerV3 * packager,gboolean strict,GError ** error)1707 modulemd_packager_v3_parse_rpm_components (yaml_parser_t *parser,
1708 ModulemdPackagerV3 *packager,
1709 gboolean strict,
1710 GError **error)
1711 {
1712 MODULEMD_INIT_TRACE ();
1713 MMD_INIT_YAML_EVENT (event);
1714 gboolean done = FALSE;
1715 g_autoptr (GError) nested_error = NULL;
1716 g_autoptr (ModulemdComponentRpm) component = NULL;
1717
1718 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1719
1720 /* We *must* get a MAPPING_START here */
1721 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
1722 if (event.type != YAML_MAPPING_START_EVENT)
1723 {
1724 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1725 error,
1726 event,
1727 "Got %s instead of MAPPING_START in rpm components.",
1728 mmd_yaml_get_event_name (event.type));
1729 }
1730
1731 while (!done)
1732 {
1733 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
1734
1735 switch (event.type)
1736 {
1737 case YAML_MAPPING_END_EVENT: done = TRUE; break;
1738
1739 case YAML_SCALAR_EVENT:
1740 component = modulemd_component_rpm_parse_yaml (
1741 parser,
1742 (const gchar *)event.data.scalar.value,
1743 strict,
1744 &nested_error);
1745 if (!component)
1746 {
1747 g_propagate_error (error, g_steal_pointer (&nested_error));
1748 return FALSE;
1749 }
1750 modulemd_packager_v3_add_component (packager,
1751 (ModulemdComponent *)component);
1752 g_clear_pointer (&component, g_object_unref);
1753 break;
1754
1755 default:
1756 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1757 error,
1758 event,
1759 "Unexpected YAML event in RPM component: %s",
1760 mmd_yaml_get_event_name (event.type));
1761 break;
1762 }
1763 yaml_event_delete (&event);
1764 }
1765
1766 return TRUE;
1767 }
1768
1769
1770 static gboolean
modulemd_packager_v3_parse_module_components(yaml_parser_t * parser,ModulemdPackagerV3 * packager,gboolean strict,GError ** error)1771 modulemd_packager_v3_parse_module_components (yaml_parser_t *parser,
1772 ModulemdPackagerV3 *packager,
1773 gboolean strict,
1774 GError **error)
1775 {
1776 MODULEMD_INIT_TRACE ();
1777 MMD_INIT_YAML_EVENT (event);
1778 gboolean done = FALSE;
1779 g_autoptr (GError) nested_error = NULL;
1780 g_autoptr (ModulemdComponentModule) component = NULL;
1781
1782 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1783
1784 /* We *must* get a MAPPING_START here */
1785 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
1786 if (event.type != YAML_MAPPING_START_EVENT)
1787 {
1788 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1789 error,
1790 event,
1791 "Got %s instead of MAPPING_START in module components.",
1792 mmd_yaml_get_event_name (event.type));
1793 }
1794
1795 while (!done)
1796 {
1797 YAML_PARSER_PARSE_WITH_EXIT_BOOL (parser, &event, error);
1798
1799 switch (event.type)
1800 {
1801 case YAML_MAPPING_END_EVENT: done = TRUE; break;
1802
1803 case YAML_SCALAR_EVENT:
1804 component = modulemd_component_module_parse_yaml (
1805 parser,
1806 (const gchar *)event.data.scalar.value,
1807 strict,
1808 &nested_error);
1809 if (!component)
1810 {
1811 g_propagate_error (error, g_steal_pointer (&nested_error));
1812 return FALSE;
1813 }
1814 modulemd_packager_v3_add_component (packager,
1815 (ModulemdComponent *)component);
1816 g_clear_pointer (&component, g_object_unref);
1817 break;
1818
1819 default:
1820 MMD_YAML_ERROR_EVENT_EXIT_BOOL (
1821 error,
1822 event,
1823 "Unexpected YAML event in module component: %s",
1824 mmd_yaml_get_event_name (event.type));
1825 break;
1826 }
1827 yaml_event_delete (&event);
1828 }
1829
1830 return TRUE;
1831 }
1832
1833
1834 gboolean
modulemd_packager_v3_emit_yaml(ModulemdPackagerV3 * self,yaml_emitter_t * emitter,GError ** error)1835 modulemd_packager_v3_emit_yaml (ModulemdPackagerV3 *self,
1836 yaml_emitter_t *emitter,
1837 GError **error)
1838 {
1839 MODULEMD_INIT_TRACE ();
1840 g_autoptr (GError) nested_error = NULL;
1841 gsize i;
1842 g_autoptr (GPtrArray) keys = NULL;
1843 gboolean ret;
1844
1845 /* Emit document headers */
1846 if (!modulemd_yaml_emit_document_headers (
1847 emitter, MODULEMD_YAML_DOC_PACKAGER, MD_PACKAGER_VERSION_THREE, error))
1848 {
1849 return FALSE;
1850 }
1851
1852 /* Start data: */
1853 EMIT_MAPPING_START (emitter, error);
1854
1855 if (modulemd_packager_v3_get_module_name (self) != NULL)
1856 {
1857 EMIT_KEY_VALUE (
1858 emitter, error, "name", modulemd_packager_v3_get_module_name (self));
1859 }
1860
1861 if (modulemd_packager_v3_get_stream_name (self) != NULL)
1862 {
1863 EMIT_KEY_VALUE_FULL (emitter,
1864 error,
1865 "stream",
1866 modulemd_packager_v3_get_stream_name (self),
1867 YAML_DOUBLE_QUOTED_SCALAR_STYLE);
1868 }
1869
1870 EMIT_KEY_VALUE (
1871 emitter, error, "summary", modulemd_packager_v3_get_summary (self));
1872 EMIT_KEY_VALUE_FULL (emitter,
1873 error,
1874 "description",
1875 modulemd_packager_v3_get_description (self),
1876 YAML_FOLDED_SCALAR_STYLE);
1877
1878 if (NON_EMPTY_TABLE (self->module_licenses))
1879 {
1880 EMIT_STRING_SET (emitter, error, "license", self->module_licenses);
1881 }
1882
1883 if (self->xmd != NULL)
1884 {
1885 EMIT_SCALAR (emitter, error, "xmd");
1886 if (!modulemd_yaml_emit_variant (emitter, self->xmd, error))
1887 {
1888 return FALSE;
1889 }
1890 }
1891
1892 if (NON_EMPTY_TABLE (self->build_configs))
1893 {
1894 EMIT_SCALAR (emitter, error, "configurations");
1895 EMIT_SEQUENCE_START (emitter, error);
1896 keys =
1897 modulemd_ordered_str_keys (self->build_configs, modulemd_strcmp_sort);
1898 for (i = 0; i < keys->len; i++)
1899 {
1900 ret = modulemd_build_config_emit_yaml (
1901 g_hash_table_lookup (self->build_configs,
1902 g_ptr_array_index (keys, i)),
1903 emitter,
1904 error);
1905 if (!ret)
1906 {
1907 return FALSE;
1908 }
1909 }
1910 EMIT_SEQUENCE_END (emitter, error);
1911 }
1912
1913
1914 if (self->community || self->documentation || self->tracker)
1915 {
1916 EMIT_SCALAR (emitter, error, "references");
1917 EMIT_MAPPING_START (emitter, error);
1918 EMIT_KEY_VALUE_IF_SET (emitter, error, "community", self->community);
1919 EMIT_KEY_VALUE_IF_SET (
1920 emitter, error, "documentation", self->documentation);
1921 EMIT_KEY_VALUE_IF_SET (emitter, error, "tracker", self->tracker);
1922 EMIT_MAPPING_END (emitter, error);
1923 }
1924
1925 EMIT_HASHTABLE_VALUES_IF_NON_EMPTY (
1926 emitter, error, "profiles", self->profiles, modulemd_profile_emit_yaml);
1927
1928 if (NON_EMPTY_TABLE (self->rpm_api))
1929 {
1930 EMIT_SCALAR (emitter, error, "api");
1931 EMIT_MAPPING_START (emitter, error);
1932 EMIT_STRING_SET (emitter, error, "rpms", self->rpm_api);
1933 EMIT_MAPPING_END (emitter, error);
1934 }
1935
1936 if (NON_EMPTY_TABLE (self->rpm_filters))
1937 {
1938 EMIT_SCALAR (emitter, error, "filter");
1939 EMIT_MAPPING_START (emitter, error);
1940 EMIT_STRING_SET (emitter, error, "rpms", self->rpm_filters);
1941 EMIT_MAPPING_END (emitter, error);
1942 }
1943
1944 if (NON_EMPTY_TABLE (self->demodularized_rpms))
1945 {
1946 EMIT_SCALAR (emitter, error, "demodularized");
1947 EMIT_MAPPING_START (emitter, error);
1948 EMIT_STRING_SET (emitter, error, "rpms", self->demodularized_rpms);
1949 EMIT_MAPPING_END (emitter, error);
1950 }
1951
1952 if (NON_EMPTY_TABLE (self->rpm_components) ||
1953 NON_EMPTY_TABLE (self->module_components))
1954 {
1955 EMIT_SCALAR (emitter, error, "components");
1956 EMIT_MAPPING_START (emitter, error);
1957 EMIT_HASHTABLE_VALUES_IF_NON_EMPTY (emitter,
1958 error,
1959 "rpms",
1960 self->rpm_components,
1961 modulemd_component_rpm_emit_yaml);
1962 EMIT_HASHTABLE_VALUES_IF_NON_EMPTY (emitter,
1963 error,
1964 "modules",
1965 self->module_components,
1966 modulemd_component_module_emit_yaml);
1967 EMIT_MAPPING_END (emitter, error);
1968 }
1969
1970 /* The "data" mapping */
1971 EMIT_MAPPING_END (emitter, error);
1972 /* The overall document mapping */
1973 EMIT_MAPPING_END (emitter, error);
1974 if (!mmd_emitter_end_document (emitter, error))
1975 {
1976 return FALSE;
1977 }
1978
1979 return TRUE;
1980 }
1981