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-component-module.h"
15 #include "private/modulemd-component-module-private.h"
16 #include "private/modulemd-component-private.h"
17 #include "private/modulemd-util.h"
18 #include "private/modulemd-yaml.h"
19
20 #define CM_DEFAULT_STRING "__UNSET_COMPONENT_MODULE__"
21
22 struct _ModulemdComponentModule
23 {
24 GObject parent_instance;
25
26 gchar *ref;
27 gchar *repository;
28 };
29
30 G_DEFINE_TYPE (ModulemdComponentModule,
31 modulemd_component_module,
32 MODULEMD_TYPE_COMPONENT)
33
34 enum
35 {
36 PROP_0,
37
38 PROP_REF,
39 PROP_REPOSITORY,
40
41 N_PROPS
42 };
43
44 static GParamSpec *properties[N_PROPS];
45
46
47 ModulemdComponentModule *
modulemd_component_module_new(const gchar * key)48 modulemd_component_module_new (const gchar *key)
49 {
50 return g_object_new (MODULEMD_TYPE_COMPONENT_MODULE, "name", key, NULL);
51 }
52
53
54 static void
modulemd_component_module_finalize(GObject * object)55 modulemd_component_module_finalize (GObject *object)
56 {
57 ModulemdComponentModule *self = (ModulemdComponentModule *)object;
58
59 g_clear_pointer (&self->ref, g_free);
60 g_clear_pointer (&self->repository, g_free);
61
62 G_OBJECT_CLASS (modulemd_component_module_parent_class)->finalize (object);
63 }
64
65
66 static gboolean
modulemd_component_module_equals(ModulemdComponent * self_1,ModulemdComponent * self_2)67 modulemd_component_module_equals (ModulemdComponent *self_1,
68 ModulemdComponent *self_2)
69 {
70 ModulemdComponentModule *module_self_1 = NULL;
71 ModulemdComponentModule *module_self_2 = NULL;
72
73 g_return_val_if_fail (MODULEMD_IS_COMPONENT_MODULE (self_1), FALSE);
74 module_self_1 = MODULEMD_COMPONENT_MODULE (self_1);
75 g_return_val_if_fail (MODULEMD_IS_COMPONENT_MODULE (self_2), FALSE);
76 module_self_2 = MODULEMD_COMPONENT_MODULE (self_2);
77
78 if (!MODULEMD_COMPONENT_CLASS (modulemd_component_module_parent_class)
79 ->equals (self_1, self_2))
80 {
81 return FALSE;
82 }
83
84 if (g_strcmp0 (module_self_1->ref, module_self_2->ref) != 0)
85 {
86 return FALSE;
87 }
88
89 if (g_strcmp0 (module_self_1->repository, module_self_2->repository) != 0)
90 {
91 return FALSE;
92 }
93
94 return TRUE;
95 }
96
97
98 static ModulemdComponent *
modulemd_component_module_copy(ModulemdComponent * self,const gchar * key)99 modulemd_component_module_copy (ModulemdComponent *self, const gchar *key)
100 {
101 ModulemdComponentModule *module_self = NULL;
102 g_autoptr (ModulemdComponentModule) copy = NULL;
103 g_return_val_if_fail (MODULEMD_IS_COMPONENT_MODULE (self), NULL);
104 module_self = MODULEMD_COMPONENT_MODULE (self);
105
106 copy = MODULEMD_COMPONENT_MODULE (
107 MODULEMD_COMPONENT_CLASS (modulemd_component_module_parent_class)
108 ->copy (self, key));
109
110 modulemd_component_module_set_ref (
111 copy, modulemd_component_module_get_ref (module_self));
112 modulemd_component_module_set_repository (
113 copy, modulemd_component_module_get_repository (module_self));
114
115 return MODULEMD_COMPONENT (g_steal_pointer (©));
116 }
117
118
119 void
modulemd_component_module_set_ref(ModulemdComponentModule * self,const gchar * ref)120 modulemd_component_module_set_ref (ModulemdComponentModule *self,
121 const gchar *ref)
122 {
123 g_return_if_fail (MODULEMD_IS_COMPONENT_MODULE (self));
124
125 g_clear_pointer (&self->ref, g_free);
126 self->ref = g_strdup (ref);
127
128 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_REF]);
129 }
130
131
132 const gchar *
modulemd_component_module_get_ref(ModulemdComponentModule * self)133 modulemd_component_module_get_ref (ModulemdComponentModule *self)
134 {
135 g_return_val_if_fail (MODULEMD_IS_COMPONENT_MODULE (self), NULL);
136
137 return self->ref;
138 }
139
140
141 void
modulemd_component_module_set_repository(ModulemdComponentModule * self,const gchar * repository)142 modulemd_component_module_set_repository (ModulemdComponentModule *self,
143 const gchar *repository)
144 {
145 g_return_if_fail (MODULEMD_IS_COMPONENT_MODULE (self));
146
147 g_clear_pointer (&self->repository, g_free);
148 self->repository = g_strdup (repository);
149
150 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_REPOSITORY]);
151 }
152
153
154 const gchar *
modulemd_component_module_get_repository(ModulemdComponentModule * self)155 modulemd_component_module_get_repository (ModulemdComponentModule *self)
156 {
157 g_return_val_if_fail (MODULEMD_IS_COMPONENT_MODULE (self), NULL);
158
159 return self->repository;
160 }
161
162
163 static void
modulemd_component_module_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)164 modulemd_component_module_get_property (GObject *object,
165 guint prop_id,
166 GValue *value,
167 GParamSpec *pspec)
168 {
169 ModulemdComponentModule *self = MODULEMD_COMPONENT_MODULE (object);
170
171 switch (prop_id)
172 {
173 case PROP_REF:
174 g_value_set_string (value, modulemd_component_module_get_ref (self));
175 break;
176 case PROP_REPOSITORY:
177 g_value_set_string (value,
178 modulemd_component_module_get_repository (self));
179 break;
180 default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
181 }
182 }
183
184
185 static void
modulemd_component_module_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)186 modulemd_component_module_set_property (GObject *object,
187 guint prop_id,
188 const GValue *value,
189 GParamSpec *pspec)
190 {
191 ModulemdComponentModule *self = MODULEMD_COMPONENT_MODULE (object);
192
193 switch (prop_id)
194 {
195 case PROP_REF:
196 modulemd_component_module_set_ref (self, g_value_get_string (value));
197 break;
198 case PROP_REPOSITORY:
199 modulemd_component_module_set_repository (self,
200 g_value_get_string (value));
201 break;
202 default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
203 }
204 }
205
206
207 static void
modulemd_component_module_class_init(ModulemdComponentModuleClass * klass)208 modulemd_component_module_class_init (ModulemdComponentModuleClass *klass)
209 {
210 GObjectClass *object_class = G_OBJECT_CLASS (klass);
211 ModulemdComponentClass *component_class =
212 MODULEMD_COMPONENT_CLASS (object_class);
213
214 object_class->finalize = modulemd_component_module_finalize;
215 object_class->get_property = modulemd_component_module_get_property;
216 object_class->set_property = modulemd_component_module_set_property;
217
218 component_class->copy = modulemd_component_module_copy;
219 component_class->equals = modulemd_component_module_equals;
220
221 properties[PROP_REF] =
222 g_param_spec_string ("ref",
223 "Ref",
224 "The commit ID in the SCM repository.",
225 CM_DEFAULT_STRING,
226 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
227 properties[PROP_REPOSITORY] =
228 g_param_spec_string ("repository",
229 "Repository",
230 "The URI of the SCM repository.",
231 CM_DEFAULT_STRING,
232 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
233 g_object_class_install_properties (object_class, N_PROPS, properties);
234 }
235
236
237 static void
modulemd_component_module_init(ModulemdComponentModule * self)238 modulemd_component_module_init (ModulemdComponentModule *self)
239 {
240 /* Nothing to init */
241 }
242
243
244 gboolean
modulemd_component_module_emit_yaml(ModulemdComponentModule * self,yaml_emitter_t * emitter,GError ** error)245 modulemd_component_module_emit_yaml (ModulemdComponentModule *self,
246 yaml_emitter_t *emitter,
247 GError **error)
248 {
249 MODULEMD_INIT_TRACE ();
250 MMD_INIT_YAML_EVENT (event);
251
252 if (!modulemd_component_emit_yaml_start (
253 MODULEMD_COMPONENT (self), emitter, error))
254 {
255 return FALSE;
256 }
257
258 if (modulemd_component_module_get_repository (self) != NULL)
259 {
260 if (!mmd_emitter_scalar (
261 emitter, "repository", YAML_PLAIN_SCALAR_STYLE, error))
262 {
263 return FALSE;
264 }
265
266 if (!mmd_emitter_scalar (emitter,
267 modulemd_component_module_get_repository (self),
268 YAML_PLAIN_SCALAR_STYLE,
269 error))
270 {
271 return FALSE;
272 }
273 }
274
275 if (modulemd_component_module_get_ref (self) != NULL)
276 {
277 if (!mmd_emitter_scalar (emitter, "ref", YAML_PLAIN_SCALAR_STYLE, error))
278 {
279 return FALSE;
280 }
281
282 if (!mmd_emitter_scalar (emitter,
283 modulemd_component_module_get_ref (self),
284 YAML_PLAIN_SCALAR_STYLE,
285 error))
286 {
287 return FALSE;
288 }
289 }
290
291 if (!modulemd_component_emit_yaml_build_common (
292 MODULEMD_COMPONENT (self), emitter, error))
293 {
294 return FALSE;
295 }
296
297 if (!mmd_emitter_end_mapping (emitter, error))
298 {
299 return FALSE;
300 }
301
302 return TRUE;
303 }
304
305
306 ModulemdComponentModule *
modulemd_component_module_parse_yaml(yaml_parser_t * parser,const gchar * name,gboolean strict,GError ** error)307 modulemd_component_module_parse_yaml (yaml_parser_t *parser,
308 const gchar *name,
309 gboolean strict,
310 GError **error)
311 {
312 MODULEMD_INIT_TRACE ();
313 MMD_INIT_YAML_EVENT (event);
314 gboolean done = FALSE;
315 gboolean in_map = FALSE;
316 g_autofree gchar *value = NULL;
317 gint buildorder = 0;
318 g_autoptr (ModulemdComponentModule) m = NULL;
319
320 g_autoptr (GError) nested_error = NULL;
321
322 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
323
324 m = modulemd_component_module_new (name);
325
326 while (!done)
327 {
328 YAML_PARSER_PARSE_WITH_EXIT (parser, &event, error);
329
330 switch (event.type)
331 {
332 case YAML_MAPPING_START_EVENT: in_map = TRUE; break;
333
334 case YAML_MAPPING_END_EVENT:
335 in_map = FALSE;
336 done = TRUE;
337 break;
338
339 case YAML_SCALAR_EVENT:
340 if (!in_map)
341 {
342 MMD_YAML_ERROR_EVENT_EXIT (
343 error, event, "Missing mapping in module component entry");
344 break;
345 }
346 if (g_str_equal ((const gchar *)event.data.scalar.value,
347 "rationale"))
348 {
349 value = modulemd_yaml_parse_string (parser, &nested_error);
350 if (!value)
351 {
352 MMD_YAML_ERROR_EVENT_EXIT (
353 error,
354 event,
355 "Failed to parse rationale in component: %s",
356 nested_error->message);
357 }
358
359 modulemd_component_set_rationale (MODULEMD_COMPONENT (m), value);
360 g_clear_pointer (&value, g_free);
361 }
362 else if (g_str_equal ((const gchar *)event.data.scalar.value,
363 "repository"))
364 {
365 value = modulemd_yaml_parse_string (parser, &nested_error);
366 if (!value)
367 {
368 MMD_YAML_ERROR_EVENT_EXIT (
369 error,
370 event,
371 "Failed to parse repository in component: %s",
372 nested_error->message);
373 }
374
375 modulemd_component_module_set_repository (m, value);
376 g_clear_pointer (&value, g_free);
377 }
378 else if (g_str_equal ((const gchar *)event.data.scalar.value, "ref"))
379 {
380 value = modulemd_yaml_parse_string (parser, &nested_error);
381 if (!value)
382 {
383 MMD_YAML_ERROR_EVENT_EXIT (
384 error,
385 event,
386 "Failed to parse ref in component: %s",
387 nested_error->message);
388 }
389
390 modulemd_component_module_set_ref (m, value);
391 g_clear_pointer (&value, g_free);
392 }
393 else if (g_str_equal ((const gchar *)event.data.scalar.value,
394 "buildonly"))
395 {
396 if (!modulemd_component_parse_buildonly (
397 MODULEMD_COMPONENT (m), parser, &nested_error))
398 {
399 MMD_YAML_ERROR_EVENT_EXIT (
400 error,
401 event,
402 "Failed to parse buildonly in component: %s",
403 nested_error->message);
404 }
405 }
406 else if (g_str_equal ((const gchar *)event.data.scalar.value,
407 "buildorder"))
408 {
409 buildorder = modulemd_yaml_parse_int64 (parser, &nested_error);
410 if (buildorder == 0 && nested_error != NULL)
411 {
412 MMD_YAML_ERROR_EVENT_EXIT (
413 error,
414 event,
415 "Failed to parse buildorder in component: %s",
416 nested_error->message);
417 }
418
419 modulemd_component_set_buildorder (MODULEMD_COMPONENT (m),
420 buildorder);
421 }
422 else
423 {
424 SKIP_UNKNOWN (parser,
425 NULL,
426 "Unexpected key in module component body: %s",
427 (const gchar *)event.data.scalar.value);
428 break;
429 }
430 break;
431 default:
432 /* We received a YAML event we shouldn't expect at this level */
433 MMD_YAML_ERROR_EVENT_EXIT (
434 error, event, "Unexpected YAML event in module component");
435 break;
436 }
437 yaml_event_delete (&event);
438 }
439
440 return g_steal_pointer (&m);
441 }
442