Skip to content

Commit

Permalink
Implement public APIs Modulemd.read_packager_file() and Modulemd.read…
Browse files Browse the repository at this point in the history
…_packager_string()

Signed-off-by: Merlin Mathesius <[email protected]>
  • Loading branch information
mmathesius authored and sgallagher committed Dec 10, 2020
1 parent ddedc61 commit 265ffcb
Show file tree
Hide file tree
Showing 5 changed files with 543 additions and 5 deletions.
40 changes: 39 additions & 1 deletion modulemd/include/modulemd-2.0/modulemd.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,12 +334,50 @@ modulemd_load_file (const gchar *yaml_file, GError **error);
* functions.
*
* Returns: (transfer full): A newly-allocated #ModulemdModuleIndex object
* initialized with the content from @yaml_file. Returns NULL and sets @error
* initialized with the content from @yaml_string. Returns NULL and sets @error
* if the metadata is not completely valid.
*
* Since: 2.10
*/
ModulemdModuleIndex *
modulemd_load_string (const gchar *yaml_string, GError **error);

/**
* modulemd_read_packager_file:
* @yaml_path: (in): A path to a YAML file containing a packager document.
* @object: (out): (transfer full): A newly allocated #ModulemdModuleStreamV2 or
* #ModulemdPackagerV3 object initialized with the content from @yaml_path.
* @error: (out): A #GError containing additional information if this function
* fails in a way that prevents program continuation.
*
* Returns: @MODULEMD_TYPE_MODULE_STREAM_V2, @MODULEMD_TYPE_PACKAGER_V3, or
* @G_TYPE_INVALID. Returns the matching GObject through the @object parameter.
* If the return value is @G_TYPE_INVALID, returns the reason as @error.
*
* Since: 2.11
*/
GType
modulemd_read_packager_file (const gchar *yaml_path,
GObject **object,
GError **error);

/**
* modulemd_read_packager_string:
* @yaml_string: (in): A YAML string containing a packager document.
* @object: (out): (transfer full): A newly allocated #ModulemdModuleStreamV2 or
* #ModulemdPackagerV3 object initialized with the content from @yaml_string.
* @error: (out): A #GError containing additional information if this function
* fails in a way that prevents program continuation.
*
* Returns: @MODULEMD_TYPE_MODULE_STREAM_V2, @MODULEMD_TYPE_PACKAGER_V3, or
* @G_TYPE_INVALID. Returns the matching GObject through the @object parameter.
* If the return value is @G_TYPE_INVALID, returns the reason as @error.
*
* Since: 2.11
*/
GType
modulemd_read_packager_string (const gchar *yaml_string,
GObject **object,
GError **error);

G_END_DECLS
17 changes: 17 additions & 0 deletions modulemd/include/private/modulemd-module-stream-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -449,4 +449,21 @@ modulemd_module_stream_clear_autogen_module_name (ModulemdModuleStream *self);
void
modulemd_module_stream_clear_autogen_stream_name (ModulemdModuleStream *self);

/**
* modulemd_module_stream_upgrade_v1_to_v2:
* @from (in): A #ModulemdModuleStreamV1 object.
* @error: (out): A #GError that will return the reason for an upgrade error.
*
* Return an upgraded copy of this object. Does not modify the original.
*
* Returns: (transfer full): A newly-allocated #ModulemdModuleStreamV2 copy of
* @from upgraded to V2. Returns NULL and sets @error appropriately if the
* upgrade could not be completed automatically.
*
* Since: 2.11
*/
ModulemdModuleStream *
modulemd_module_stream_upgrade_v1_to_v2 (ModulemdModuleStream *from);


G_END_DECLS
5 changes: 1 addition & 4 deletions modulemd/modulemd-module-stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,9 +461,6 @@ modulemd_module_stream_copy (ModulemdModuleStream *self,
}


static ModulemdModuleStream *
modulemd_module_stream_upgrade_v1_to_v2 (ModulemdModuleStream *from);

ModulemdModuleStream *
modulemd_module_stream_upgrade (ModulemdModuleStream *self,
guint64 mdversion,
Expand Down Expand Up @@ -651,7 +648,7 @@ modulemd_module_stream_upgrade_ext (ModulemdModuleStream *self,
}


static ModulemdModuleStream *
ModulemdModuleStream *
modulemd_module_stream_upgrade_v1_to_v2 (ModulemdModuleStream *from)
{
ModulemdModuleStreamV1 *v1_stream = NULL;
Expand Down
243 changes: 243 additions & 0 deletions modulemd/modulemd.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@
#include "modulemd.h"
#include "config.h"

#include "private/modulemd-module-stream-private.h"
#include "private/modulemd-subdocument-info-private.h"
#include "private/modulemd-packager-v3-private.h"

#include <errno.h>
#include <inttypes.h>

const gchar *
modulemd_get_version (void)
Expand Down Expand Up @@ -102,3 +107,241 @@ verify_load (gboolean ret,

return g_object_ref (idx);
}

static GType
modulemd_read_packager_from_parser (yaml_parser_t *parser,
GObject **object,
GError **error);

GType
modulemd_read_packager_file (const gchar *yaml_path,
GObject **object,
GError **error)
{
MMD_INIT_YAML_PARSER (parser);
g_autoptr (FILE) yaml_stream = NULL;
gint err;

g_return_val_if_fail (yaml_path, G_TYPE_INVALID);
g_return_val_if_fail (object, G_TYPE_INVALID);
g_return_val_if_fail (error == NULL || *error == NULL, G_TYPE_INVALID);

errno = 0;
yaml_stream = g_fopen (yaml_path, "rbe");
err = errno;

if (!yaml_stream)
{
g_set_error (error,
MODULEMD_YAML_ERROR,
MMD_YAML_ERROR_OPEN,
"%s",
g_strerror (err));
return G_TYPE_INVALID;
}

yaml_parser_set_input_file (&parser, yaml_stream);

return modulemd_read_packager_from_parser (&parser, object, error);
}

GType
modulemd_read_packager_string (const gchar *yaml_string,
GObject **object,
GError **error)
{
MMD_INIT_YAML_PARSER (parser);

g_return_val_if_fail (yaml_string, G_TYPE_INVALID);
g_return_val_if_fail (object, G_TYPE_INVALID);
g_return_val_if_fail (error == NULL || *error == NULL, G_TYPE_INVALID);

yaml_parser_set_input_string (
&parser, (const unsigned char *)yaml_string, strlen (yaml_string));

return modulemd_read_packager_from_parser (&parser, object, error);
}

static GType
modulemd_read_packager_from_parser (yaml_parser_t *parser,
GObject **object,
GError **error)
{
MMD_INIT_YAML_EVENT (event);
g_autoptr (ModulemdModuleStreamV1) stream_v1 = NULL;
g_autoptr (ModulemdModuleStreamV2) stream_v2 = NULL;
g_autoptr (ModulemdPackagerV3) packager_v3 = NULL;
g_autoptr (ModulemdSubdocumentInfo) subdoc = NULL;
ModulemdYamlDocumentTypeEnum doctype;
const GError *gerror = NULL;
g_autoptr (GObject) return_object = NULL;
GType return_type = G_TYPE_INVALID;

/* The first event must be the stream start */
if (!yaml_parser_parse (parser, &event))
{
g_set_error_literal (error,
MODULEMD_YAML_ERROR,
MMD_YAML_ERROR_UNPARSEABLE,
"Parser error");
return G_TYPE_INVALID;
}
if (event.type != YAML_STREAM_START_EVENT)
{
g_set_error_literal (error,
MODULEMD_YAML_ERROR,
MMD_YAML_ERROR_PARSE,
"YAML didn't begin with STREAM_START.");
return G_TYPE_INVALID;
}
yaml_event_delete (&event);

/* The second event must be the document start */
if (!yaml_parser_parse (parser, &event))
{
g_set_error_literal (error,
MODULEMD_YAML_ERROR,
MMD_YAML_ERROR_UNPARSEABLE,
"Parser error");
return G_TYPE_INVALID;
}
if (event.type != YAML_DOCUMENT_START_EVENT)
{
g_set_error_literal (error,
MODULEMD_YAML_ERROR,
MMD_YAML_ERROR_PARSE,
"YAML didn't begin with STREAM_START.");
return G_TYPE_INVALID;
}
yaml_event_delete (&event);

subdoc = modulemd_yaml_parse_document_type (parser);
gerror = modulemd_subdocument_info_get_gerror (subdoc);
if (gerror)
{
g_set_error (error,
gerror->domain,
gerror->code,
"Parse error identifying document type and version: %s",
gerror->message);
return G_TYPE_INVALID;
}


doctype = modulemd_subdocument_info_get_doctype (subdoc);

switch (doctype)
{
case MODULEMD_YAML_DOC_PACKAGER:
if (modulemd_subdocument_info_get_mdversion (subdoc) <
MD_PACKAGER_VERSION_TWO)
{
g_set_error (error,
MODULEMD_YAML_ERROR,
MMD_YAML_ERROR_PARSE,
"Invalid mdversion for a packager document");
return G_TYPE_INVALID;
}

if (modulemd_subdocument_info_get_mdversion (subdoc) ==
MD_PACKAGER_VERSION_THREE)
{
packager_v3 = modulemd_packager_v3_parse_yaml (subdoc, error);
if (!packager_v3)
{
return G_TYPE_INVALID;
}

return_object = (GObject *)g_steal_pointer (&packager_v3);
return_type = MODULEMD_TYPE_PACKAGER_V3;
break;
}

/* Falling through intentionally: packager V2 format is handled below */

case MODULEMD_YAML_DOC_MODULESTREAM:
switch (modulemd_subdocument_info_get_mdversion (subdoc))
{
case MD_MODULESTREAM_VERSION_ONE:
stream_v1 =
modulemd_module_stream_v1_parse_yaml (subdoc, FALSE, error);
if (!stream_v1)
{
return G_TYPE_INVALID;
}

stream_v2 = MODULEMD_MODULE_STREAM_V2 (
modulemd_module_stream_upgrade_v1_to_v2 (
MODULEMD_MODULE_STREAM (stream_v1)));
if (!stream_v2)
{
/* This should be impossible, since there are no failure returns
* from modulemd_module_stream_upgrade_v1_to_v2()
*/
g_set_error (error,
MODULEMD_ERROR,
MMD_ERROR_UPGRADE,
"Upgrading to v2 failed for an unknown reason");
return G_TYPE_INVALID;
}

return_object = (GObject *)g_steal_pointer (&stream_v2);
return_type = MODULEMD_TYPE_MODULE_STREAM_V2;
break;

case MD_MODULESTREAM_VERSION_TWO:
stream_v2 = modulemd_module_stream_v2_parse_yaml (
subdoc, FALSE, doctype == MODULEMD_YAML_DOC_PACKAGER, error);
if (!stream_v2)
{
return G_TYPE_INVALID;
}

return_object = (GObject *)g_steal_pointer (&stream_v2);
return_type = MODULEMD_TYPE_MODULE_STREAM_V2;
break;

default:
g_set_error (error,
MODULEMD_YAML_ERROR,
MMD_YAML_ERROR_PARSE,
"Invalid mdversion (%" PRIu64
") for a modulemd[-stream] document",
modulemd_subdocument_info_get_mdversion (subdoc));
return G_TYPE_INVALID;
}
break;

default:
g_set_error (
error,
MODULEMD_YAML_ERROR,
MMD_YAML_ERROR_PARSE,
"Expected `document: modulemd[-stream] or modulemd-packager`, got %d",
modulemd_subdocument_info_get_doctype (subdoc));
return G_TYPE_INVALID;
}

/* The last event must be the stream end */
if (!yaml_parser_parse (parser, &event))
{
g_set_error_literal (error,
MODULEMD_YAML_ERROR,
MMD_YAML_ERROR_UNPARSEABLE,
"Parser error");
return G_TYPE_INVALID;
}

if (event.type != YAML_STREAM_END_EVENT)
{
g_set_error_literal (error,
MODULEMD_YAML_ERROR,
MMD_YAML_ERROR_PARSE,
"YAML contained more than a single subdocument");
return G_TYPE_INVALID;
}
yaml_event_delete (&event);

*object = g_steal_pointer (&return_object);
return return_type;
}
Loading

0 comments on commit 265ffcb

Please sign in to comment.