Skip to content

Commit

Permalink
Add Modulemd.ModuleIndex.dump_to_custom()
Browse files Browse the repository at this point in the history
In order to support YAML streams from arbitrary sources (such as those
being written to a compressed file through an intermediate library), we
need to support writing through a custom function. This patch enables
consumers of libmodulemd to have indirect access to libyaml's
yaml_parser_set_output() to accomplish this.

Adds a basic test to read through a long string and verify that it
produced an index with the read module.

Related: fedora-modularity#208

Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
  • Loading branch information
sgallagher committed Apr 5, 2019
1 parent 0c4fcce commit 147393d
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 0 deletions.
47 changes: 47 additions & 0 deletions modulemd/v2/include/modulemd-2.0/modulemd-module-index.h
Expand Up @@ -100,6 +100,32 @@ typedef gint (*ModulemdReadHandler) (void *data,
size_t *size_read);


/**
* ModulemdWriteHandler:
* @data: (inout): A private pointer that includes the data source.
* @buffer: (out): The buffer with bytes to be written.
* @size: (in): The size of the buffer.
*
* The prototype of a write handler.
*
* The write handler is called when the emitter needs to flush the accumulated
* characters to the output. The handler should write @size bytes of the
* @buffer to the output.
*
* This handler is identical to a
* [yaml_write_handler_t](https://github.com/yaml/libyaml/blob/master/include/yaml.h#L1478)
* but is included here to avoid depending on yaml.h in modulemd headers.
*
* Returns: On success, the handler must return 1. If the handler failed,
* the returned value must be 0.
*
* Since: 2.3
*/
typedef gint (*ModulemdWriteHandler) (void *data,
unsigned char *buffer,
size_t size);


/**
* modulemd_module_index_new:
*
Expand Down Expand Up @@ -254,6 +280,27 @@ modulemd_module_index_dump_to_stream (ModulemdModuleIndex *self,
GError **error);


/**
* modulemd_module_index_dump_to_custom: (skip)
* @self: This #ModulemdModuleIndex
* @custom_write_fn: (in): A #ModulemdWriteHandler
* @custom_pvt_data: (inout): The private data needed by the
* #ModulemdWriteHandler
* @error: (out): A #GError containing the reason the function failed, NULL if
* the function succeeded
*
* Returns: TRUE if written successfully, FALSE and sets error appropriately in
* the event of an error.
*
* Since: 2.3
*/
gboolean
modulemd_module_index_dump_to_custom (ModulemdModuleIndex *self,
ModulemdWriteHandler custom_write_fn,
void *custom_pvt_data,
GError **error);


/**
* modulemd_module_index_get_module_names_as_strv: (rename-to modulemd_module_index_get_module_names)
* @self: This #ModulemdModuleIndex
Expand Down
15 changes: 15 additions & 0 deletions modulemd/v2/modulemd-module-index.c
Expand Up @@ -590,6 +590,21 @@ modulemd_module_index_dump_to_stream (ModulemdModuleIndex *self,
}


gboolean
modulemd_module_index_dump_to_custom (ModulemdModuleIndex *self,
ModulemdWriteHandler custom_write_fn,
void *custom_pvt_data,
GError **error)
{
g_return_val_if_fail (MODULEMD_IS_MODULE_INDEX (self), FALSE);

MMD_INIT_YAML_EMITTER (emitter);
yaml_emitter_set_output (&emitter, custom_write_fn, custom_pvt_data);

return modulemd_module_index_dump_to_emitter (self, &emitter, error);
}


GStrv
modulemd_module_index_get_module_names_as_strv (ModulemdModuleIndex *self)
{
Expand Down
134 changes: 134 additions & 0 deletions modulemd/v2/tests/test-modulemd-moduleindex.c
Expand Up @@ -840,6 +840,133 @@ module_index_test_custom_read (ModuleIndexFixture *fixture,
}


static void
module_index_test_custom_write (ModuleIndexFixture *fixture,
gconstpointer user_data)
{
g_autoptr (ModulemdModuleIndex) index = NULL;
g_autoptr (GPtrArray) failures = NULL;
g_autoptr (GError) error = NULL;
g_autofree gchar *output_string = NULL;
g_autoptr (modulemd_yaml_string) yaml_string =
g_malloc0_n (1, sizeof (modulemd_yaml_string));


// clang-format off
g_autofree gchar *str = g_strdup(
"---\n"
"document: modulemd\n"
"version: 2\n"
"data:\n"
" name: testmodule\n"
" stream: master\n"
" version: 20180405123256\n"
" context: c2c572ec\n"
" arch: x86_64\n"
" summary: A test module in all its beautiful beauty\n"
" description: >-\n"
" This module demonstrates how to write simple modulemd files And can be used for\n"
" testing the build and release pipeline.\n"
" license:\n"
" module:\n"
" - MIT\n"
" content:\n"
" - GPL+ or Artistic\n"
" - MIT\n"
" xmd:\n"
" mbs:\n"
" scmurl: https://src.fedoraproject.org/modules/testmodule.git?#0d33e028e4561f82ea43f670ee6366675cd6a6fe\n"
" commit: 0d33e028e4561f82ea43f670ee6366675cd6a6fe\n"
" buildrequires:\n"
" platform:\n"
" ref: virtual\n"
" stream: f29\n"
" filtered_rpms: []\n"
" version: 4\n"
" rpms:\n"
" perl-List-Compare:\n"
" ref: c6a689a6ce2683b15b32f83e6cb5d43ffd3816f5\n"
" tangerine:\n"
" ref: 239ada495d941ceefd8f359e1d8a47877fbba4a9\n"
" perl-Tangerine:\n"
" ref: 7e96446223f1ad84a26c7cf23d6591cd9f6326c6\n"
" requires:\n"
" platform:\n"
" ref: virtual\n"
" stream: f29\n"
" filtered_rpms: []\n"
" version: 4\n"
" dependencies:\n"
" - buildrequires:\n"
" platform: [f29]\n"
" requires:\n"
" platform: [f29]\n"
" references:\n"
" community: https://docs.pagure.org/modularity/\n"
" documentation: https://fedoraproject.org/wiki/Fedora_Packaging_Guidelines_for_Modules\n"
" profiles:\n"
" default:\n"
" rpms:\n"
" - tangerine\n"
" api:\n"
" rpms:\n"
" - perl-Tangerine\n"
" - tangerine\n"
" components:\n"
" rpms:\n"
" perl-List-Compare:\n"
" rationale: A dependency of tangerine.\n"
" repository: git://pkgs.fedoraproject.org/rpms/perl-List-Compare\n"
" cache: http://pkgs.fedoraproject.org/repo/pkgs/perl-List-Compare\n"
" ref: master\n"
" perl-Tangerine:\n"
" rationale: Provides API for this module and is a dependency of tangerine.\n"
" repository: git://pkgs.fedoraproject.org/rpms/perl-Tangerine\n"
" cache: http://pkgs.fedoraproject.org/repo/pkgs/perl-Tangerine\n"
" ref: 7e96446\n"
" tangerine:\n"
" rationale: Provides API for this module.\n"
" repository: git://pkgs.fedoraproject.org/rpms/tangerine\n"
" cache: http://pkgs.fedoraproject.org/repo/pkgs/tangerine\n"
" ref: master\n"
" buildorder: 10\n"
" artifacts:\n"
" rpms:\n"
" - perl-List-Compare-0:0.53-9.module_1588+5eed94c6.noarch\n"
" - perl-Tangerine-0:0.22-2.module_1588+5eed94c6.noarch\n"
" - tangerine-0:0.22-7.module_1588+5eed94c6.noarch\n"
"...\n");
// clang-format on

index = modulemd_module_index_new ();

g_assert_true (modulemd_module_index_update_from_string (
index, str, TRUE, &failures, &error));
g_assert_cmpint (failures->len, ==, 0);
g_assert_no_error (error);
g_clear_pointer (&failures, g_ptr_array_unref);

/* Verify we did indeed get the module we expected */
g_assert_nonnull (modulemd_module_index_get_module (index, "testmodule"));


/* Write it out to another string
* This is mainly to have a baseline to compare against
*/
output_string = modulemd_module_index_dump_to_string (index, &error);
g_assert_nonnull (output_string);
g_assert_no_error (error);


/* Write it out to a string using a custom emitter */
g_assert_true (modulemd_module_index_dump_to_custom (
index, write_yaml_string, yaml_string, &error));
g_assert_nonnull (yaml_string->str);
g_assert_no_error (error);
g_assert_cmpstr (yaml_string->str, ==, output_string);
}


int
main (int argc, char *argv[])
{
Expand Down Expand Up @@ -906,5 +1033,12 @@ main (int argc, char *argv[])
module_index_test_custom_read,
NULL);

g_test_add ("/modulemd/v2/module/index/custom_write",
ModuleIndexFixture,
NULL,
NULL,
module_index_test_custom_write,
NULL);

return g_test_run ();
}

0 comments on commit 147393d

Please sign in to comment.