Skip to content

Commit 265ffcb

Browse files
mmathesiussgallagher
authored andcommitted
Implement public APIs Modulemd.read_packager_file() and Modulemd.read_packager_string()
Signed-off-by: Merlin Mathesius <[email protected]>
1 parent ddedc61 commit 265ffcb

File tree

5 files changed

+543
-5
lines changed

5 files changed

+543
-5
lines changed

modulemd/include/modulemd-2.0/modulemd.h

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,12 +334,50 @@ modulemd_load_file (const gchar *yaml_file, GError **error);
334334
* functions.
335335
*
336336
* Returns: (transfer full): A newly-allocated #ModulemdModuleIndex object
337-
* initialized with the content from @yaml_file. Returns NULL and sets @error
337+
* initialized with the content from @yaml_string. Returns NULL and sets @error
338338
* if the metadata is not completely valid.
339339
*
340340
* Since: 2.10
341341
*/
342342
ModulemdModuleIndex *
343343
modulemd_load_string (const gchar *yaml_string, GError **error);
344344

345+
/**
346+
* modulemd_read_packager_file:
347+
* @yaml_path: (in): A path to a YAML file containing a packager document.
348+
* @object: (out): (transfer full): A newly allocated #ModulemdModuleStreamV2 or
349+
* #ModulemdPackagerV3 object initialized with the content from @yaml_path.
350+
* @error: (out): A #GError containing additional information if this function
351+
* fails in a way that prevents program continuation.
352+
*
353+
* Returns: @MODULEMD_TYPE_MODULE_STREAM_V2, @MODULEMD_TYPE_PACKAGER_V3, or
354+
* @G_TYPE_INVALID. Returns the matching GObject through the @object parameter.
355+
* If the return value is @G_TYPE_INVALID, returns the reason as @error.
356+
*
357+
* Since: 2.11
358+
*/
359+
GType
360+
modulemd_read_packager_file (const gchar *yaml_path,
361+
GObject **object,
362+
GError **error);
363+
364+
/**
365+
* modulemd_read_packager_string:
366+
* @yaml_string: (in): A YAML string containing a packager document.
367+
* @object: (out): (transfer full): A newly allocated #ModulemdModuleStreamV2 or
368+
* #ModulemdPackagerV3 object initialized with the content from @yaml_string.
369+
* @error: (out): A #GError containing additional information if this function
370+
* fails in a way that prevents program continuation.
371+
*
372+
* Returns: @MODULEMD_TYPE_MODULE_STREAM_V2, @MODULEMD_TYPE_PACKAGER_V3, or
373+
* @G_TYPE_INVALID. Returns the matching GObject through the @object parameter.
374+
* If the return value is @G_TYPE_INVALID, returns the reason as @error.
375+
*
376+
* Since: 2.11
377+
*/
378+
GType
379+
modulemd_read_packager_string (const gchar *yaml_string,
380+
GObject **object,
381+
GError **error);
382+
345383
G_END_DECLS

modulemd/include/private/modulemd-module-stream-private.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,4 +449,21 @@ modulemd_module_stream_clear_autogen_module_name (ModulemdModuleStream *self);
449449
void
450450
modulemd_module_stream_clear_autogen_stream_name (ModulemdModuleStream *self);
451451

452+
/**
453+
* modulemd_module_stream_upgrade_v1_to_v2:
454+
* @from (in): A #ModulemdModuleStreamV1 object.
455+
* @error: (out): A #GError that will return the reason for an upgrade error.
456+
*
457+
* Return an upgraded copy of this object. Does not modify the original.
458+
*
459+
* Returns: (transfer full): A newly-allocated #ModulemdModuleStreamV2 copy of
460+
* @from upgraded to V2. Returns NULL and sets @error appropriately if the
461+
* upgrade could not be completed automatically.
462+
*
463+
* Since: 2.11
464+
*/
465+
ModulemdModuleStream *
466+
modulemd_module_stream_upgrade_v1_to_v2 (ModulemdModuleStream *from);
467+
468+
452469
G_END_DECLS

modulemd/modulemd-module-stream.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -461,9 +461,6 @@ modulemd_module_stream_copy (ModulemdModuleStream *self,
461461
}
462462

463463

464-
static ModulemdModuleStream *
465-
modulemd_module_stream_upgrade_v1_to_v2 (ModulemdModuleStream *from);
466-
467464
ModulemdModuleStream *
468465
modulemd_module_stream_upgrade (ModulemdModuleStream *self,
469466
guint64 mdversion,
@@ -651,7 +648,7 @@ modulemd_module_stream_upgrade_ext (ModulemdModuleStream *self,
651648
}
652649

653650

654-
static ModulemdModuleStream *
651+
ModulemdModuleStream *
655652
modulemd_module_stream_upgrade_v1_to_v2 (ModulemdModuleStream *from)
656653
{
657654
ModulemdModuleStreamV1 *v1_stream = NULL;

modulemd/modulemd.c

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414
#include "modulemd.h"
1515
#include "config.h"
1616

17+
#include "private/modulemd-module-stream-private.h"
1718
#include "private/modulemd-subdocument-info-private.h"
19+
#include "private/modulemd-packager-v3-private.h"
20+
21+
#include <errno.h>
22+
#include <inttypes.h>
1823

1924
const gchar *
2025
modulemd_get_version (void)
@@ -102,3 +107,241 @@ verify_load (gboolean ret,
102107

103108
return g_object_ref (idx);
104109
}
110+
111+
static GType
112+
modulemd_read_packager_from_parser (yaml_parser_t *parser,
113+
GObject **object,
114+
GError **error);
115+
116+
GType
117+
modulemd_read_packager_file (const gchar *yaml_path,
118+
GObject **object,
119+
GError **error)
120+
{
121+
MMD_INIT_YAML_PARSER (parser);
122+
g_autoptr (FILE) yaml_stream = NULL;
123+
gint err;
124+
125+
g_return_val_if_fail (yaml_path, G_TYPE_INVALID);
126+
g_return_val_if_fail (object, G_TYPE_INVALID);
127+
g_return_val_if_fail (error == NULL || *error == NULL, G_TYPE_INVALID);
128+
129+
errno = 0;
130+
yaml_stream = g_fopen (yaml_path, "rbe");
131+
err = errno;
132+
133+
if (!yaml_stream)
134+
{
135+
g_set_error (error,
136+
MODULEMD_YAML_ERROR,
137+
MMD_YAML_ERROR_OPEN,
138+
"%s",
139+
g_strerror (err));
140+
return G_TYPE_INVALID;
141+
}
142+
143+
yaml_parser_set_input_file (&parser, yaml_stream);
144+
145+
return modulemd_read_packager_from_parser (&parser, object, error);
146+
}
147+
148+
GType
149+
modulemd_read_packager_string (const gchar *yaml_string,
150+
GObject **object,
151+
GError **error)
152+
{
153+
MMD_INIT_YAML_PARSER (parser);
154+
155+
g_return_val_if_fail (yaml_string, G_TYPE_INVALID);
156+
g_return_val_if_fail (object, G_TYPE_INVALID);
157+
g_return_val_if_fail (error == NULL || *error == NULL, G_TYPE_INVALID);
158+
159+
yaml_parser_set_input_string (
160+
&parser, (const unsigned char *)yaml_string, strlen (yaml_string));
161+
162+
return modulemd_read_packager_from_parser (&parser, object, error);
163+
}
164+
165+
static GType
166+
modulemd_read_packager_from_parser (yaml_parser_t *parser,
167+
GObject **object,
168+
GError **error)
169+
{
170+
MMD_INIT_YAML_EVENT (event);
171+
g_autoptr (ModulemdModuleStreamV1) stream_v1 = NULL;
172+
g_autoptr (ModulemdModuleStreamV2) stream_v2 = NULL;
173+
g_autoptr (ModulemdPackagerV3) packager_v3 = NULL;
174+
g_autoptr (ModulemdSubdocumentInfo) subdoc = NULL;
175+
ModulemdYamlDocumentTypeEnum doctype;
176+
const GError *gerror = NULL;
177+
g_autoptr (GObject) return_object = NULL;
178+
GType return_type = G_TYPE_INVALID;
179+
180+
/* The first event must be the stream start */
181+
if (!yaml_parser_parse (parser, &event))
182+
{
183+
g_set_error_literal (error,
184+
MODULEMD_YAML_ERROR,
185+
MMD_YAML_ERROR_UNPARSEABLE,
186+
"Parser error");
187+
return G_TYPE_INVALID;
188+
}
189+
if (event.type != YAML_STREAM_START_EVENT)
190+
{
191+
g_set_error_literal (error,
192+
MODULEMD_YAML_ERROR,
193+
MMD_YAML_ERROR_PARSE,
194+
"YAML didn't begin with STREAM_START.");
195+
return G_TYPE_INVALID;
196+
}
197+
yaml_event_delete (&event);
198+
199+
/* The second event must be the document start */
200+
if (!yaml_parser_parse (parser, &event))
201+
{
202+
g_set_error_literal (error,
203+
MODULEMD_YAML_ERROR,
204+
MMD_YAML_ERROR_UNPARSEABLE,
205+
"Parser error");
206+
return G_TYPE_INVALID;
207+
}
208+
if (event.type != YAML_DOCUMENT_START_EVENT)
209+
{
210+
g_set_error_literal (error,
211+
MODULEMD_YAML_ERROR,
212+
MMD_YAML_ERROR_PARSE,
213+
"YAML didn't begin with STREAM_START.");
214+
return G_TYPE_INVALID;
215+
}
216+
yaml_event_delete (&event);
217+
218+
subdoc = modulemd_yaml_parse_document_type (parser);
219+
gerror = modulemd_subdocument_info_get_gerror (subdoc);
220+
if (gerror)
221+
{
222+
g_set_error (error,
223+
gerror->domain,
224+
gerror->code,
225+
"Parse error identifying document type and version: %s",
226+
gerror->message);
227+
return G_TYPE_INVALID;
228+
}
229+
230+
231+
doctype = modulemd_subdocument_info_get_doctype (subdoc);
232+
233+
switch (doctype)
234+
{
235+
case MODULEMD_YAML_DOC_PACKAGER:
236+
if (modulemd_subdocument_info_get_mdversion (subdoc) <
237+
MD_PACKAGER_VERSION_TWO)
238+
{
239+
g_set_error (error,
240+
MODULEMD_YAML_ERROR,
241+
MMD_YAML_ERROR_PARSE,
242+
"Invalid mdversion for a packager document");
243+
return G_TYPE_INVALID;
244+
}
245+
246+
if (modulemd_subdocument_info_get_mdversion (subdoc) ==
247+
MD_PACKAGER_VERSION_THREE)
248+
{
249+
packager_v3 = modulemd_packager_v3_parse_yaml (subdoc, error);
250+
if (!packager_v3)
251+
{
252+
return G_TYPE_INVALID;
253+
}
254+
255+
return_object = (GObject *)g_steal_pointer (&packager_v3);
256+
return_type = MODULEMD_TYPE_PACKAGER_V3;
257+
break;
258+
}
259+
260+
/* Falling through intentionally: packager V2 format is handled below */
261+
262+
case MODULEMD_YAML_DOC_MODULESTREAM:
263+
switch (modulemd_subdocument_info_get_mdversion (subdoc))
264+
{
265+
case MD_MODULESTREAM_VERSION_ONE:
266+
stream_v1 =
267+
modulemd_module_stream_v1_parse_yaml (subdoc, FALSE, error);
268+
if (!stream_v1)
269+
{
270+
return G_TYPE_INVALID;
271+
}
272+
273+
stream_v2 = MODULEMD_MODULE_STREAM_V2 (
274+
modulemd_module_stream_upgrade_v1_to_v2 (
275+
MODULEMD_MODULE_STREAM (stream_v1)));
276+
if (!stream_v2)
277+
{
278+
/* This should be impossible, since there are no failure returns
279+
* from modulemd_module_stream_upgrade_v1_to_v2()
280+
*/
281+
g_set_error (error,
282+
MODULEMD_ERROR,
283+
MMD_ERROR_UPGRADE,
284+
"Upgrading to v2 failed for an unknown reason");
285+
return G_TYPE_INVALID;
286+
}
287+
288+
return_object = (GObject *)g_steal_pointer (&stream_v2);
289+
return_type = MODULEMD_TYPE_MODULE_STREAM_V2;
290+
break;
291+
292+
case MD_MODULESTREAM_VERSION_TWO:
293+
stream_v2 = modulemd_module_stream_v2_parse_yaml (
294+
subdoc, FALSE, doctype == MODULEMD_YAML_DOC_PACKAGER, error);
295+
if (!stream_v2)
296+
{
297+
return G_TYPE_INVALID;
298+
}
299+
300+
return_object = (GObject *)g_steal_pointer (&stream_v2);
301+
return_type = MODULEMD_TYPE_MODULE_STREAM_V2;
302+
break;
303+
304+
default:
305+
g_set_error (error,
306+
MODULEMD_YAML_ERROR,
307+
MMD_YAML_ERROR_PARSE,
308+
"Invalid mdversion (%" PRIu64
309+
") for a modulemd[-stream] document",
310+
modulemd_subdocument_info_get_mdversion (subdoc));
311+
return G_TYPE_INVALID;
312+
}
313+
break;
314+
315+
default:
316+
g_set_error (
317+
error,
318+
MODULEMD_YAML_ERROR,
319+
MMD_YAML_ERROR_PARSE,
320+
"Expected `document: modulemd[-stream] or modulemd-packager`, got %d",
321+
modulemd_subdocument_info_get_doctype (subdoc));
322+
return G_TYPE_INVALID;
323+
}
324+
325+
/* The last event must be the stream end */
326+
if (!yaml_parser_parse (parser, &event))
327+
{
328+
g_set_error_literal (error,
329+
MODULEMD_YAML_ERROR,
330+
MMD_YAML_ERROR_UNPARSEABLE,
331+
"Parser error");
332+
return G_TYPE_INVALID;
333+
}
334+
335+
if (event.type != YAML_STREAM_END_EVENT)
336+
{
337+
g_set_error_literal (error,
338+
MODULEMD_YAML_ERROR,
339+
MMD_YAML_ERROR_PARSE,
340+
"YAML contained more than a single subdocument");
341+
return G_TYPE_INVALID;
342+
}
343+
yaml_event_delete (&event);
344+
345+
*object = g_steal_pointer (&return_object);
346+
return return_type;
347+
}

0 commit comments

Comments
 (0)