diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..011e9f8 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/modulemd-2.0.0.tar.xz diff --git a/.libmodulemd.metadata b/.libmodulemd.metadata new file mode 100644 index 0000000..c29b91c --- /dev/null +++ b/.libmodulemd.metadata @@ -0,0 +1 @@ +e242f10ac0185da47cc54d0253cb0f8a80633ff4 SOURCES/modulemd-2.0.0.tar.xz diff --git a/SOURCES/0001-Don-t-fail-merges-when-default-streams-differ.patch b/SOURCES/0001-Don-t-fail-merges-when-default-streams-differ.patch new file mode 100644 index 0000000..1daa97a --- /dev/null +++ b/SOURCES/0001-Don-t-fail-merges-when-default-streams-differ.patch @@ -0,0 +1,543 @@ +From 774f36026f1d3a4215be67845c2873135ceab6e4 Mon Sep 17 00:00:00 2001 +From: Stephen Gallagher +Date: Wed, 16 Jan 2019 13:21:44 -0500 +Subject: [PATCH] Don't fail merges when default streams differ + +Instead of failing the merge on a default stream conflict, we will +instead treat it as having no default set. This is safe because if +the module is not yet installed, then this just means its packages +aren't visible and it needs to be selected explicitly. + +If some packages from it are already installed, then the module +stream is already set, and thus changing the default won't matter. + +Update documentation to reflect modified field in Defaults + +Resolves: rhbz#1666871 + +Signed-off-by: Stephen Gallagher +--- + .../modulemd-1.0/private/modulemd-private.h | 2 + + modulemd/v1/modulemd-defaults.c | 39 +++++++---- + modulemd/v1/tests/test-modulemd-defaults.c | 66 ++++++++++++++++++- + .../modulemd-module-index-merger.h | 18 +++-- + .../private/modulemd-defaults-v1-private.h | 2 + + modulemd/v2/modulemd-defaults-v1.c | 59 +++++++++++------ + modulemd/v2/tests/ModulemdTests/merger.py | 33 +++++++--- + .../v2/tests/test_data/overriding-nodejs.yaml | 11 ++++ + test_data/defaults/overriding-nodejs.yaml | 10 +++ + 9 files changed, 191 insertions(+), 49 deletions(-) + create mode 100644 modulemd/v2/tests/test_data/overriding-nodejs.yaml + create mode 100644 test_data/defaults/overriding-nodejs.yaml + +diff --git a/modulemd/v1/include/modulemd-1.0/private/modulemd-private.h b/modulemd/v1/include/modulemd-1.0/private/modulemd-private.h +index 20604efab843de6ac64cd9e181ce93d7e3a798fe..e9a785aed0d38598ce08d58e7e507d01698788a0 100644 +--- a/modulemd/v1/include/modulemd-1.0/private/modulemd-private.h ++++ b/modulemd/v1/include/modulemd-1.0/private/modulemd-private.h +@@ -24,10 +24,12 @@ enum + MD_VERSION_MAX = G_MAXUINT64 + }; + + #define MD_VERSION_LATEST MD_VERSION_2 + ++#define DEFAULT_MERGE_CONFLICT "__merge_conflict__" ++ + ModulemdModule * + modulemd_module_new_from_modulestream (ModulemdModuleStream *stream); + + ModulemdModuleStream * + modulemd_module_peek_modulestream (ModulemdModule *self); +diff --git a/modulemd/v1/modulemd-defaults.c b/modulemd/v1/modulemd-defaults.c +index 77ce30733945e30ffb8368986fa8c54c45697b5a..d44076eef0ac3bffae05f74b852fb6b51c2aee64 100644 +--- a/modulemd/v1/modulemd-defaults.c ++++ b/modulemd/v1/modulemd-defaults.c +@@ -12,10 +12,11 @@ + */ + + #include "modulemd.h" + #include "modulemd-defaults.h" + #include "modulemd-simpleset.h" ++#include "private/modulemd-private.h" + #include "private/modulemd-yaml.h" + + + GQuark + modulemd_defaults_error_quark (void) +@@ -146,19 +147,38 @@ modulemd_defaults_set_default_stream (ModulemdDefaults *self, + const gchar * + modulemd_defaults_peek_default_stream (ModulemdDefaults *self) + { + g_return_val_if_fail (self, NULL); + ++ if (self->default_stream && ++ g_str_equal (self->default_stream, DEFAULT_MERGE_CONFLICT)) ++ { ++ /* During an index merge, we determined that this was in conflict ++ * with another set of ModulemdDefaults for the same module. If we ++ * see this, treat it as no default stream when querying for it. ++ */ ++ return NULL; ++ } + return self->default_stream; + } + + + gchar * + modulemd_defaults_dup_default_stream (ModulemdDefaults *self) + { + g_return_val_if_fail (self, NULL); + ++ if (self->default_stream && ++ g_str_equal (self->default_stream, DEFAULT_MERGE_CONFLICT)) ++ { ++ /* During an index merge, we determined that this was in conflict ++ * with another set of ModulemdDefaults for the same module. If we ++ * see this, treat it as no default stream when querying for it. ++ */ ++ return NULL; ++ } ++ + return g_strdup (self->default_stream); + } + + + void +@@ -753,28 +773,25 @@ modulemd_defaults_merge (ModulemdDefaults *first, + /* They had the same 'modified' value (such as both zero, for + * backwards-compatibility with 1.7.x and older. + * Merge them as best we can. + */ + ++ defaults = modulemd_defaults_copy (first); ++ + /* First check for incompatibilities with the streams */ +- if (g_strcmp0 (modulemd_defaults_peek_default_stream (first), +- modulemd_defaults_peek_default_stream (second))) ++ if (g_strcmp0 (first->default_stream, second->default_stream)) + { + /* Default streams don't match and override is not set. + * Return an error + */ +- g_set_error ( +- error, +- MODULEMD_DEFAULTS_ERROR, +- MODULEMD_DEFAULTS_ERROR_CONFLICTING_STREAMS, +- "Conflicting default streams when merging defaults for module %s", +- modulemd_defaults_peek_module_name (first)); +- return NULL; ++ /* They have conflicting default streams */ ++ g_info ("Module stream mismatch in merge: %s != %s", ++ first->default_stream, ++ second->default_stream); ++ modulemd_defaults_set_default_stream (defaults, DEFAULT_MERGE_CONFLICT); + } + +- defaults = modulemd_defaults_copy (first); +- + /* Merge the profile defaults */ + profile_defaults = modulemd_defaults_peek_profile_defaults (defaults); + + g_hash_table_iter_init (&iter, + modulemd_defaults_peek_profile_defaults (second)); +diff --git a/modulemd/v1/tests/test-modulemd-defaults.c b/modulemd/v1/tests/test-modulemd-defaults.c +index 5d032d83cbca4046af13719f68bdbc6778d6879e..35142b885b3ec30f5109d53befe17be3e08d7b5a 100644 +--- a/modulemd/v1/tests/test-modulemd-defaults.c ++++ b/modulemd/v1/tests/test-modulemd-defaults.c +@@ -602,10 +602,11 @@ modulemd_defaults_test_prioritizer (DefaultsFixture *fixture, + { + g_autofree gchar *yaml_base_path = NULL; + g_autofree gchar *yaml_override_path = NULL; + g_autoptr (GPtrArray) base_objects = NULL; + g_autoptr (GPtrArray) override_objects = NULL; ++ g_autoptr (GPtrArray) override_nodejs_objects = NULL; + g_autoptr (GPtrArray) merged_objects = NULL; + g_autoptr (ModulemdPrioritizer) prioritizer = NULL; + g_autoptr (GError) error = NULL; + GHashTable *htable = NULL; + gint64 prio; +@@ -618,10 +619,22 @@ modulemd_defaults_test_prioritizer (DefaultsFixture *fixture, + + base_objects = modulemd_objects_from_file (yaml_base_path, &error); + g_assert_nonnull (base_objects); + g_assert_cmpint (base_objects->len, ==, 7); + ++ ++ yaml_override_path = ++ g_strdup_printf ("%s/test_data/defaults/overriding-nodejs.yaml", ++ g_getenv ("MESON_SOURCE_ROOT")); ++ g_assert_nonnull (yaml_override_path); ++ ++ override_nodejs_objects = ++ modulemd_objects_from_file (yaml_override_path, &error); ++ g_clear_pointer (&yaml_override_path, g_free); ++ g_assert_nonnull (override_nodejs_objects); ++ g_assert_cmpint (override_nodejs_objects->len, ==, 1); ++ + yaml_override_path = g_strdup_printf ( + "%s/test_data/defaults/overriding.yaml", g_getenv ("MESON_SOURCE_ROOT")); + g_assert_nonnull (yaml_override_path); + + override_objects = modulemd_objects_from_file (yaml_override_path, &error); +@@ -659,10 +672,52 @@ modulemd_defaults_test_prioritizer (DefaultsFixture *fixture, + fprintf (stderr, "Merge error: %s", error->message); + } + g_assert_true (result); + + ++ /* ++ * Test that importing the nodejs overrides at the same priority level fails. ++ * ++ * This YAML has a conflicting default stream which should be ignored and set ++ * to "no default stream". ++ */ ++ ++ result = modulemd_prioritizer_add ( ++ prioritizer, override_nodejs_objects, prio, &error); ++ g_assert_true (result); ++ ++ merged_objects = modulemd_prioritizer_resolve (prioritizer, &error); ++ g_assert_nonnull (merged_objects); ++ g_assert_cmpint (merged_objects->len, ==, 3); ++ ++ for (gint i = 0; i < merged_objects->len; i++) ++ { ++ if (MODULEMD_IS_DEFAULTS (g_ptr_array_index (merged_objects, i))) ++ { ++ defaults = g_ptr_array_index (merged_objects, i); ++ if (!g_strcmp0 (modulemd_defaults_peek_module_name (defaults), ++ "nodejs")) ++ { ++ g_assert_null (modulemd_defaults_peek_default_stream (defaults)); ++ } ++ } ++ } ++ ++ g_clear_pointer (&merged_objects, g_ptr_array_unref); ++ ++ ++ /* Start over and test profile conflicts */ ++ g_clear_pointer (&prioritizer, g_object_unref); ++ prioritizer = modulemd_prioritizer_new (); ++ result = modulemd_prioritizer_add (prioritizer, base_objects, prio, &error); ++ if (!result) ++ { ++ fprintf (stderr, "Merge error: %s", error->message); ++ } ++ g_assert_true (result); ++ ++ + /* + * Test that importing the overrides at the same priority level fails. + * + * These objects have several conflicts with the base objects that cannot be + * merged. +@@ -671,11 +726,11 @@ modulemd_defaults_test_prioritizer (DefaultsFixture *fixture, + modulemd_prioritizer_add (prioritizer, override_objects, prio, &error); + g_assert_false (result); + g_assert_cmpstr ( + g_quark_to_string (error->domain), ==, "modulemd-defaults-error-quark"); + g_assert_cmpint ( +- error->code, ==, MODULEMD_DEFAULTS_ERROR_CONFLICTING_STREAMS); ++ error->code, ==, MODULEMD_DEFAULTS_ERROR_CONFLICTING_PROFILES); + g_clear_pointer (&error, g_error_free); + + /* The object's internal state is undefined after an error, so delete it */ + g_clear_pointer (&prioritizer, g_object_unref); + +@@ -987,11 +1042,11 @@ modulemd_defaults_test_index_prioritizer (DefaultsFixture *fixture, + modulemd_prioritizer_add_index (prioritizer, override_index, prio, &error); + g_assert_false (result); + g_assert_cmpstr ( + g_quark_to_string (error->domain), ==, "modulemd-defaults-error-quark"); + g_assert_cmpint ( +- error->code, ==, MODULEMD_DEFAULTS_ERROR_CONFLICTING_STREAMS); ++ error->code, ==, MODULEMD_DEFAULTS_ERROR_CONFLICTING_PROFILES); + g_clear_pointer (&error, g_error_free); + + /* The object's internal state is undefined after an error, so delete it */ + g_clear_pointer (&prioritizer, g_object_unref); + +@@ -1138,10 +1193,15 @@ modulemd_regressions_issue44 (DefaultsFixture *fixture, + g_assert_true (result); + + + /* Add another almost-identical document, except with a conflicting default + * stream set. ++ * ++ * NOTE: when this was written (for issue 44 on GitHub), this was meant to be ++ * a hard error. As of 1.8.1 we expect this to just result in having no ++ * default stream for this module. This test has been slightly modified so ++ * that the expected result is now a pass. + */ + yaml_conflicting_path = g_strdup_printf ( + "%s/test_data/defaults/issue44-2.yaml", g_getenv ("MESON_SOURCE_ROOT")); + g_assert_nonnull (yaml_conflicting_path); + +@@ -1149,11 +1209,11 @@ modulemd_regressions_issue44 (DefaultsFixture *fixture, + modulemd_objects_from_file (yaml_conflicting_path, &error); + g_assert_nonnull (conflicting_objects); + + result = + modulemd_prioritizer_add (prioritizer, conflicting_objects, 0, &error); +- g_assert_false (result); ++ g_assert_true (result); + } + + + static void + modulemd_regressions_issue45 (DefaultsFixture *fixture, +diff --git a/modulemd/v2/include/modulemd-2.0/modulemd-module-index-merger.h b/modulemd/v2/include/modulemd-2.0/modulemd-module-index-merger.h +index 27cccb738dc805724268afa04acc13d4e250eae2..b019f0ed856684a003e9c2f6abefc70e1448246a 100644 +--- a/modulemd/v2/include/modulemd-2.0/modulemd-module-index-merger.h ++++ b/modulemd/v2/include/modulemd-2.0/modulemd-module-index-merger.h +@@ -51,22 +51,30 @@ G_BEGIN_DECLS + * there exists two #ModulemdModuleStream entries that have different content + * for the same NSVC, the behavior is undefined. + * + * Merging #ModulemdDefaults entries behaves as follows: + * ++ * - Within a ModuleIndex, if two or more default entries reference the same ++ * module, the one with the highest modified field will be used and the ++ * others discarded. ++ * - When merging ModuleIndexes, if two or more indexes contain Defaults for ++ * the same module, but different modified values, the one with the highest ++ * modified value will be used and the others discarded. + * - Any module default that is provided by a single repository is + * authoritative. + * - If the repos have different priorities (not common), then the default for + * this module and stream name coming from the repo of higher priority will +- * be used and the default from the lower-priority repo will not be included. ++ * be used and the default from the lower-priority repo will not be included ++ * even if it has a higher modified value. + * - If the repos have the same priority (such as "fedora" and "updates" in the +- * Fedora Project), the entries will be merged as follows: +- * - If both repositories specify a default stream for the module, use it. ++ * Fedora Project) and modified value, the entries will be merged as follows: ++ * - If both repositories specify the same default stream for the module, use ++ * it. + * - If either repository specifies a default stream for the module and the + * other does not, use the one specified. +- * - If both repositories specify different streams, this is an unresolvable +- * merge conflict and the merge resolution will fail and report an error. ++ * - If both repositories specify different default streams, the merge will ++ * unset the default stream and proceed with the merge. + * - If both repositories specify a set of default profiles for a stream and + * the sets are equivalent, use that set. + * - If one repository specifies a set of default profiles for a stream and + * the other does not, use the one specified. + * - If both repositories specify a set of default profiles for a stream and +diff --git a/modulemd/v2/include/modulemd-2.0/private/modulemd-defaults-v1-private.h b/modulemd/v2/include/modulemd-2.0/private/modulemd-defaults-v1-private.h +index 9cac6cc53175a0eecca986f4fa96a7b7b1070957..de2ede98e6fb49bfd792b5f2913868fad6ff27db 100644 +--- a/modulemd/v2/include/modulemd-2.0/private/modulemd-defaults-v1-private.h ++++ b/modulemd/v2/include/modulemd-2.0/private/modulemd-defaults-v1-private.h +@@ -26,10 +26,12 @@ G_BEGIN_DECLS + * @stability: private + * @short_description: #ModulemdDefault methods that should only be used by + * internal consumers. + */ + ++#define DEFAULT_MERGE_CONFLICT "__merge_conflict__" ++ + /** + * modulemd_defaults_v1_parse_yaml: + * @subdoc: (in): A #ModulemdSubdocumentInfo representing a defaults document + * of metadata version 1. + * @strict: (in): Whether the parser should return failure if it encounters an +diff --git a/modulemd/v2/modulemd-defaults-v1.c b/modulemd/v2/modulemd-defaults-v1.c +index c8f983105b529519365d0a653d8d07715f610b97..1c1cdd7b1036734a477b72d12f12526af1de777d 100644 +--- a/modulemd/v2/modulemd-defaults-v1.c ++++ b/modulemd/v2/modulemd-defaults-v1.c +@@ -179,11 +179,22 @@ modulemd_defaults_v1_get_default_stream (ModulemdDefaultsV1 *self, + { + const gchar *default_stream = NULL; + g_return_val_if_fail (MODULEMD_IS_DEFAULTS_V1 (self), NULL); + + if (!intent) +- return self->default_stream; ++ { ++ if (self->default_stream && ++ g_str_equal (self->default_stream, DEFAULT_MERGE_CONFLICT)) ++ { ++ /* During an index merge, we determined that this was in conflict ++ * with another set of ModulemdDefaults for the same module. If we ++ * see this, treat it as no default stream when querying for it. ++ */ ++ return NULL; ++ } ++ return self->default_stream; ++ } + + default_stream = g_hash_table_lookup (self->intent_default_streams, intent); + if (default_stream) + { + if (default_stream[0] == '\0') +@@ -1159,12 +1170,10 @@ ModulemdDefaults * + modulemd_defaults_v1_merge (const gchar *module_name, + ModulemdDefaultsV1 *from, + ModulemdDefaultsV1 *into, + GError **error) + { +- const gchar *into_default_stream; +- const gchar *from_default_stream; + g_autoptr (ModulemdDefaultsV1) merged = NULL; + GHashTableIter iter; + gpointer key, value; + GHashTable *intent_profiles = NULL; + GHashTable *merged_intent_profiles = NULL; +@@ -1175,37 +1184,45 @@ modulemd_defaults_v1_merge (const gchar *module_name, + g_autoptr (GError) nested_error = NULL; + + merged = modulemd_defaults_v1_new (module_name); + + /* Merge the default streams */ +- into_default_stream = modulemd_defaults_v1_get_default_stream (into, NULL); +- from_default_stream = modulemd_defaults_v1_get_default_stream (from, NULL); +- +- if (into_default_stream && !from_default_stream) ++ if (into->default_stream && !from->default_stream) + { + modulemd_defaults_v1_set_default_stream ( +- merged, into_default_stream, NULL); ++ merged, into->default_stream, NULL); + } +- else if (from_default_stream && !into_default_stream) ++ else if (from->default_stream && !into->default_stream) + { + modulemd_defaults_v1_set_default_stream ( +- merged, from_default_stream, NULL); ++ merged, from->default_stream, NULL); + } +- else if (into_default_stream && from_default_stream) ++ else if (into->default_stream && from->default_stream) + { +- if (!g_str_equal (into_default_stream, from_default_stream)) ++ if (g_str_equal (into->default_stream, DEFAULT_MERGE_CONFLICT)) + { +- g_set_error (error, +- MODULEMD_ERROR, +- MODULEMD_ERROR_VALIDATE, +- "Module stream mismatch in merge: %s != %s", +- into_default_stream, +- from_default_stream); +- return NULL; ++ /* A previous pass over this same module encountered a merge ++ * conflict, so we need to propagate that. ++ */ ++ modulemd_defaults_v1_set_default_stream ( ++ merged, DEFAULT_MERGE_CONFLICT, NULL); ++ } ++ else if (!g_str_equal (into->default_stream, from->default_stream)) ++ { ++ /* They have conflicting default streams */ ++ g_info ("Module stream mismatch in merge: %s != %s", ++ into->default_stream, ++ from->default_stream); ++ modulemd_defaults_v1_set_default_stream ( ++ merged, DEFAULT_MERGE_CONFLICT, NULL); ++ } ++ else ++ { ++ /* They're the same, so store that */ ++ modulemd_defaults_v1_set_default_stream ( ++ merged, into->default_stream, NULL); + } +- modulemd_defaults_v1_set_default_stream ( +- merged, into_default_stream, NULL); + } + else + { + /* Both values were NULL. + * Nothing to do, leave it blank. +diff --git a/modulemd/v2/tests/ModulemdTests/merger.py b/modulemd/v2/tests/ModulemdTests/merger.py +index e7cbf4214bb111fbc5732fe983ee5ccee134fd83..49c2722959486aeb250d88daf7f068cacc8c3fe7 100644 +--- a/modulemd/v2/tests/ModulemdTests/merger.py ++++ b/modulemd/v2/tests/ModulemdTests/merger.py +@@ -104,26 +104,41 @@ class TestModuleIndexMerger(TestBase): + self.assertEqual( + len(httpd_defaults.get_default_profiles_for_stream('2.4', 'workstation')), 1) + self.assertEqual( + len(httpd_defaults.get_default_profiles_for_stream('2.6', 'workstation')), 3) + ++ # Get another set of objects that will override the default stream for ++ # nodejs ++ override_nodejs_index = Modulemd.ModuleIndex() ++ override_nodejs_index.update_from_file( ++ path.join( ++ self.source_root, ++ "modulemd/v2/tests/test_data/overriding-nodejs.yaml"), True) ++ ++ # Test that adding both of these at the same priority level results in ++ # the no default stream ++ merger = Modulemd.ModuleIndexMerger() ++ merger.associate_index(base_index, 0) ++ merger.associate_index(override_nodejs_index, 0) ++ ++ merged_index = merger.resolve() ++ self.assertIsNotNone(merged_index) ++ ++ nodejs = merged_index.get_module('nodejs') ++ self.assertIsNotNone(nodejs) ++ ++ nodejs_defaults = nodejs.get_defaults() ++ self.assertIsNotNone(nodejs_defaults) ++ self.assertIsNone(nodejs_defaults.get_default_stream()) ++ + # Get another set of objects that will override the above + override_index = Modulemd.ModuleIndex() + override_index.update_from_file( + path.join( + self.source_root, + "modulemd/v2/tests/test_data/overriding.yaml"), True) + +- # Test that adding both of these at the same priority level fails +- # with a merge conflict. +- merger = Modulemd.ModuleIndexMerger() +- merger.associate_index(base_index, 0) +- merger.associate_index(override_index, 0) +- +- with self.assertRaisesRegex(GLib.GError, 'Module stream mismatch in merge'): +- merged_index = merger.resolve() +- + # Test that override_index at a higher priority level succeeds + # Test that adding both of these at the same priority level fails + # with a merge conflict. + # Use randomly-selected high and low values to make sure we don't have + # sorting issues. +diff --git a/modulemd/v2/tests/test_data/overriding-nodejs.yaml b/modulemd/v2/tests/test_data/overriding-nodejs.yaml +new file mode 100644 +index 0000000000000000000000000000000000000000..b588f5f542d84755fa74fc1dbf059c0766d2a712 +--- /dev/null ++++ b/modulemd/v2/tests/test_data/overriding-nodejs.yaml +@@ -0,0 +1,11 @@ ++--- ++# Override the default stream ++document: modulemd-defaults ++version: 1 ++data: ++ module: nodejs ++ stream: '9.0' ++ profiles: ++ '6.0': [default] ++ '8.0': [super] ++ '9.0': [supermegaultra] +\ No newline at end of file +diff --git a/test_data/defaults/overriding-nodejs.yaml b/test_data/defaults/overriding-nodejs.yaml +new file mode 100644 +index 0000000000000000000000000000000000000000..937a2b899afc6b5254fd3b3e61e5b32035a3130a +--- /dev/null ++++ b/test_data/defaults/overriding-nodejs.yaml +@@ -0,0 +1,10 @@ ++--- ++document: modulemd-defaults ++version: 1 ++data: ++ module: nodejs ++ stream: '9.0' ++ profiles: ++ '6.0': [default] ++ '8.0': [super] ++ '9.0': [supermegaultra] +\ No newline at end of file +-- +2.20.1 + diff --git a/SOURCES/0001-Include-modified-value-when-copying-Defaults-objects.patch b/SOURCES/0001-Include-modified-value-when-copying-Defaults-objects.patch new file mode 100644 index 0000000..ad3ee96 --- /dev/null +++ b/SOURCES/0001-Include-modified-value-when-copying-Defaults-objects.patch @@ -0,0 +1,106 @@ +From f66d185dd5c2c1750b3626c2e0bdfeab63e427b6 Mon Sep 17 00:00:00 2001 +From: Stephen Gallagher +Date: Fri, 11 Jan 2019 08:36:11 -0500 +Subject: [PATCH] Include modified value when copying Defaults objects + +The symptom of this was that any defaults object read from a YAML +stream would end up stored in the ModuleIndex with the a zero for +the modified value. + +Signed-off-by: Stephen Gallagher +--- + modulemd/v2/modulemd-defaults.c | 7 ++++-- + modulemd/v2/tests/ModulemdTests/defaults.py | 25 +++++++++++++++++++++ + 2 files changed, 30 insertions(+), 2 deletions(-) + +diff --git a/modulemd/v2/modulemd-defaults.c b/modulemd/v2/modulemd-defaults.c +index 9e5c31b499704ae7a8543c91b9ea3bbf0dbf981d..c577d4a0c3db45319c8e0582b4cc07f3943836fa 100644 +--- a/modulemd/v2/modulemd-defaults.c ++++ b/modulemd/v2/modulemd-defaults.c +@@ -91,14 +91,18 @@ modulemd_defaults_copy (ModulemdDefaults *self) + + + static ModulemdDefaults * + modulemd_defaults_default_copy (ModulemdDefaults *self) + { ++ g_autoptr (ModulemdDefaults) copy = NULL; + g_return_val_if_fail (MODULEMD_IS_DEFAULTS (self), NULL); + +- return modulemd_defaults_new (modulemd_defaults_get_mdversion (self), ++ copy = modulemd_defaults_new (modulemd_defaults_get_mdversion (self), + modulemd_defaults_get_module_name (self)); ++ modulemd_defaults_set_modified (copy, modulemd_defaults_get_modified (self)); ++ ++ return g_steal_pointer (©); + } + + + gboolean + modulemd_defaults_validate (ModulemdDefaults *self, GError **error) +@@ -214,11 +218,10 @@ modulemd_defaults_set_modified (ModulemdDefaults *self, guint64 modified) + { + g_return_if_fail (MODULEMD_IS_DEFAULTS (self)); + + ModulemdDefaultsPrivate *priv = + modulemd_defaults_get_instance_private (self); +- + priv->modified = modified; + } + + + guint64 +diff --git a/modulemd/v2/tests/ModulemdTests/defaults.py b/modulemd/v2/tests/ModulemdTests/defaults.py +index ddac23bbed573b3725feb8cb0090fb878a1f4f22..9a783d25617fc53f59448bc32a68c6e2755dd034 100644 +--- a/modulemd/v2/tests/ModulemdTests/defaults.py ++++ b/modulemd/v2/tests/ModulemdTests/defaults.py +@@ -10,11 +10,13 @@ + # This program is free software. + # For more information on the license, see COPYING. + # For more information on free software, see + # . + ++import os + import sys ++ + try: + import unittest + import gi + gi.require_version('Modulemd', '2.0') + from gi.repository import Modulemd +@@ -92,10 +94,33 @@ class TestDefaults(TestBase): + + # Ensure we cannot set the module_name + with self.expect_signal(): + defs.props.module_name = None + ++ def test_modified(self): ++ defs = Modulemd.Defaults.new( ++ Modulemd.DefaultsVersionEnum.LATEST, 'foo') ++ self.assertIsNotNone(defs) ++ ++ self.assertEqual(defs.get_modified(), 0) ++ ++ defs.set_modified(201901110830) ++ ++ self.assertEqual(defs.get_modified(), 201901110830) ++ ++ # Load a defaults object into an Index ++ index = Modulemd.ModuleIndex.new() ++ index.update_from_file("%s/mod-defaults/spec.v1.yaml" % ( ++ os.getenv('MESON_SOURCE_ROOT')), True) ++ module_names = index.get_module_names() ++ self.assertEqual(len(module_names), 1) ++ ++ defs = index.get_module(index.get_module_names()[0]).get_defaults() ++ self.assertIsNotNone(defs) ++ ++ self.assertEqual(defs.get_modified(), 201812071200) ++ + def test_validate(self): + defs = Modulemd.Defaults.new( + Modulemd.DefaultsVersionEnum.LATEST, 'foo') + assert defs + +-- +2.20.1 + diff --git a/SPECS/libmodulemd.spec b/SPECS/libmodulemd.spec new file mode 100644 index 0000000..abf46d8 --- /dev/null +++ b/SPECS/libmodulemd.spec @@ -0,0 +1,428 @@ +%global libmodulemd_version 2.0.0 +%global libmodulemd_v1_version 1.8.0 + +Name: libmodulemd +Version: %{libmodulemd_version} +Release: 5%{?dist} +Summary: Module metadata manipulation library + +License: MIT +URL: https://github.com/fedora-modularity/libmodulemd +Source0: %{url}/releases/download/%{name}-%{version}/modulemd-%{version}.tar.xz + +BuildRequires: meson >= 0.45.1-3 +BuildRequires: pkgconfig +BuildRequires: gcc +BuildRequires: gcc-c++ +BuildRequires: pkgconfig(gobject-2.0) +BuildRequires: pkgconfig(gobject-introspection-1.0) +BuildRequires: pkgconfig(yaml-0.1) +BuildRequires: pkgconfig(gtk-doc) +BuildRequires: python3-devel +BuildRequires: python3-gobject-base +%ifarch %{valgrind_arches} +BuildRequires: valgrind +%endif + +Obsoletes: python2-modulemd < 1.3.4 +Obsoletes: python3-modulemd < 1.3.4 + +# Make sure we upgrade libmodulemd1 to match +Conflicts: libmodulemd1 < %{libmodulemd_v1_version}-%{release} + +# Patches +Patch0001: 0001-Include-modified-value-when-copying-Defaults-objects.patch +Patch0002: 0001-Don-t-fail-merges-when-default-streams-differ.patch + +%description +C Library for manipulating module metadata files. +See https://github.com/fedora-modularity/libmodulemd/blob/master/README.md for +more details. + + +%package -n python3-%{name} +Summary: Python 3 bindings for %{name} +BuildArch: noarch +Requires: libmodulemd = %{version}-%{release} +Requires: python3-gobject-base +Obsoletes: python3-modulemd < 1.3.4 + +%description -n python3-%{name} +Python 3 bindings for %{name} + + +%package devel +Summary: Development files for libmodulemd +Requires: %{name}%{?_isa} = %{version}-%{release} + + +%description devel +Development files for libmodulemd. + + +%package -n libmodulemd1 +Summary: Compatibility package for libmodulemd 1.x +Version: %{libmodulemd_v1_version} +Obsoletes: libmodulemd < 2 +Provides: libmodulemd = %{libmodulemd_v1_version}-%{release} +Provides: libmodulemd%{?_isa} = %{libmodulemd_v1_version}-%{release} + +%description -n libmodulemd1 +Compatibility library for libmodulemd 1.x + + +%package -n libmodulemd1-devel +Summary: Compatibility development package for libmodulemd 1.x +Version: %{libmodulemd_v1_version} +Requires: libmodulemd1%{?_isa} = %{libmodulemd_v1_version}-%{release} +Conflicts: %{name}-devel +Obsoletes: libmodulemd-devel < 2 +Provides: libmodulemd-devel = %{libmodulemd_v1_version}-%{release} +RemovePathPostfixes: .compat + + +%description -n libmodulemd1-devel +Development files for libmodulemd 1.x + + +%package -n python3-libmodulemd1 +Summary: Python 3 bindings for %{name}1 +Version: %{libmodulemd_v1_version} +BuildArch: noarch +Requires: libmodulemd1 = %{libmodulemd_v1_version}-%{release} +Requires: python3-gobject-base + +%description -n python3-libmodulemd1 +Python 3 bindings for libmodulemd1 + + +%prep +%autosetup -p1 -n modulemd-%{libmodulemd_version} + + +%build +%define _vpath_builddir api1 +%meson -Ddeveloper_build=false -Dbuild_api_v1=true -Dbuild_api_v2=false +%meson_build + +%define _vpath_builddir api2 +%meson -Ddeveloper_build=false -Dbuild_api_v1=false -Dbuild_api_v2=true +%meson_build + + +%check + +export LC_CTYPE=C.utf8 + +%ifarch %{power64} +# Valgrind is broken on ppc64[le] with GCC7: +# https://bugs.kde.org/show_bug.cgi?id=386945 +export MMD_SKIP_VALGRIND=1 +%endif +%ifnarch %{valgrind_arches} +export MMD_SKIP_VALGRIND=1 +%endif + +%define _vpath_builddir api1 +%meson_test + +%define _vpath_builddir api2 +%meson_test + + +%install +%define _vpath_builddir api1 +%meson_install + +%define _vpath_builddir api2 +%meson_install + +ln -s libmodulemd.so.%{libmodulemd_v1_version} \ + %{buildroot}%{_libdir}/%{name}.so.compat + + +%files +%license COPYING +%doc README.md +%{_bindir}/modulemd-validator +%{_libdir}/%{name}.so.2* +%dir %{_libdir}/girepository-1.0 +%{_libdir}/girepository-1.0/Modulemd-2.0.typelib +%{python3_sitearch}/gi/overrides/ + + +%files devel +%{_libdir}/%{name}.so +%{_libdir}/pkgconfig/modulemd-2.0.pc +%{_includedir}/modulemd-2.0/ +%dir %{_datadir}/gir-1.0 +%{_datadir}/gir-1.0/Modulemd-2.0.gir +%dir %{_datadir}/gtk-doc +%dir %{_datadir}/gtk-doc/html +%{_datadir}/gtk-doc/html/modulemd-2.0/ + + +%files -n python3-%{name} + + +%files -n python3-libmodulemd1 + + +%files -n libmodulemd1 +%license COPYING +%doc README.md +%{_bindir}/modulemd-validator-v1 +%{_libdir}/%{name}.so.1* +%dir %{_libdir}/girepository-1.0 +%{_libdir}/girepository-1.0/Modulemd-1.0.typelib + + +%files -n libmodulemd1-devel +%{_libdir}/%{name}.so.compat +%{_libdir}/pkgconfig/modulemd.pc +%{_includedir}/modulemd/ +%dir %{_datadir}/gir-1.0 +%{_datadir}/gir-1.0/Modulemd-1.0.gir +%dir %{_datadir}/gtk-doc +%dir %{_datadir}/gtk-doc/html +%{_datadir}/gtk-doc/html/modulemd-1.0/ + + +%changelog +* Fri Jan 18 2019 Stephen Gallagher - 2.0.0-5 +- Don't fail merges when default streams differ +- Resolves: rhbz#1666871 + +* Wed Jan 16 2019 Stephen Gallagher - 2.0.0-4 +- Include modified value when copying Defaults objects +- Resolves: rhbz#1665465 + +* Thu Dec 13 2018 Stephen Gallagher - 2.0.0-3 +- Keep libmodulemd1 in sync with libmodulemd + +* Thu Dec 13 2018 Stephen Gallagher - 2.0.0-2 +- Fix package location of modulemd-validator + +* Thu Dec 13 2018 Stephen Gallagher - 2.0.0-1 +- Update to 2.0.0 final +- Assorted fixes for validation +- Add modulemd-validator tool based on v2 code +- Fix a crash when merging defaults +- Add missing BuildRequires + +* Tue Dec 11 2018 Stephen Gallagher - 2.0.0-0.beta2 +- Update to 2.0.0beta2 +- Better validation of stored content during read and write operations +- ModuleIndex now returns FALSE if any subdocument fails +- Fix tests on 32-bit platforms +- Make unknown keys in YAML maps non-fatal for libmodulemd1 +- Make unknown keys in YAML maps optionally fatal for libmodulemd 2.x +- Fix RPM version requirements for libmodulemd1 + +* Mon Dec 10 2018 Stephen Gallagher - 2.0.0-0.beta1 +- Total rewrite to 2.0 API +- Resolves: rhbz#1646436 + +* Thu Aug 09 2018 Stephen Gallagher - 1.6.2-2 +- Fix backwards-incompatible API change +- Resolves: rhbz#1607083 + +* Tue Aug 07 2018 Stephen Gallagher - 1.6.2-1 +- Update to 1.6.2 +- Make buildorder a signed integer to match modulemd specification +- Obsolete unsupported pythonX-modulemd packages + +* Fri Aug 3 2018 Florian Weimer - 1.6.1-2 +- Honor %%{valgrind_arches} + +* Fri Jul 20 2018 Stephen Gallagher - 1.6.1-1 +- Update to 1.6.1 +- Fix header include ordering +- Suppress empty sections from .dump() ordering + +* Wed Jul 18 2018 Stephen Gallagher - 1.6.0-1 +- Update to 1.6.0 +- Adds Modulemd.ModuleStream object, deprecating Modulemd.Module +- Adds Modulemd.Translation and Modulemd.TranslationEntry objects +- Adds Modulemd.ImprovedModule object that collects streams, defaults and + translations together +- Adds new Modulemd.index_from_*() funtions to get a hash table of + Modulemd.ImprovedModule objects for easier searching +- Moves function documentation to the public headers +- Corrects the license headers to MIT (they were incorrectly listed as MITNFA + in previous releases) +- Makes the "eol" field optional for Modulemd.ServiceLevel +- Clean up HTML documentation +- Fixes a type error on 32-bit systems + +* Fri Jul 13 2018 Fedora Release Engineering - 1.5.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Sat Jun 23 2018 Stephen Gallagher - 1.5.2-1 +- Update to libdmodulemd 1.5.2 +- Don't free uninitialized memory + +* Fri Jun 22 2018 Stephen Gallagher - 1.5.1-2 +- Fix buildopts property not being initialized + +* Tue Jun 19 2018 Stephen Gallagher - 1.5.1-1 +- Update to version 1.5.1 +- Re-enable build-time tests + +* Mon Jun 18 2018 Stephen Gallagher - 1.5.0-2 +- Temporarily disable build-time tests + +* Mon Jun 18 2018 Stephen Gallagher - 1.5.0-1 +- Update to version 1.5.0 +- Adds support for "intents" in Modulemd.Defaults +- Adds `Modulemd.get_version()` +- Adds support for RPM whitelists in the buildopts +- Adds a new object: Modulemd.Buildopts +- Deprecates Modulemd.Module.get_rpm_buildopts() +- Deprecates Modulemd.Module.set_rpm_buildopts() +- Fixes some missing license blurbs + +* Tue May 08 2018 Stephen Gallagher - 1.4.1-1 +- Update to version 1.4.1 +- Improve output from modulemd-validator +- Drop upstreamed patches + +* Wed Apr 25 2018 Stephen Gallagher - 1.4.0-2 +- Fix pointer math error +- Fix compilation failure in Fedora build system + +* Wed Apr 25 2018 Stephen Gallagher - 1.4.0-1 +- Update to version 1.4.0 +- Adds new API for returning failed YAML subdocuments +- Stop emitting log messages by default (polluting consumer logs) +- Validate RPM artifacts for proper NEVRA format +- Improve the validator tool +- Drop upstreamed patch + +* Mon Apr 16 2018 Stephen Gallagher - 1.3.0-2 +- Fix serious error in modulemd-defaults emitter + +* Fri Apr 13 2018 Stephen Gallagher - 1.3.0-1 +- Update to version 1.3.0 +- New Public Objects: + * Modulemd.Prioritizer - tool to merge module defaults +- New Public Functions: + * Modulemd.SimpleSet.is_equal() + * Modulemd.Defaults.copy() + * Modulemd.Defaults.merge() + +* Wed Apr 04 2018 Stephen Gallagher - 1.2.0-1 +- Update to version 1.2.0 +- New Functions: + * Modulemd.objects_from_file() + * Modulemd.objects_from_string() + * Modulemd.dump() + * Modulemd.dumps() + * Modulemd.Defaults.new_from_file() + * Modulemd.Defaults.new_from_string() +- Deprecated Functions: + * Modulemd.Module.new_all_from_file() + * Modulemd.Module.new_all_from_file_ext() + * Modulemd.Module.new_all_from_string() + * Modulemd.Module.new_all_from_string_ext() + * Modulemd.Module.dump_all() + * Modulemd.Module.dumps_all() +- Bugfixes + * Properly use G_BEGIN_DECLS and G_END_DECLS in headers + * Assorted fixes for memory ownership in GObject Introspection + +* Fri Mar 23 2018 Stephen Gallagher - 1.1.3-2 +- Fix missing G_END_DECL from public headers + +* Mon Mar 19 2018 Stephen Gallagher - 1.1.3-1 +- Fix numerous memory leaks +- Drop upstreamed patch + +* Thu Mar 15 2018 Stephen Gallagher - 1.1.2-1 +- Update to version 1.1.2 +- Revert backwards-incompatible API change +- Fix version string in pkgconfig file + +* Thu Mar 15 2018 Stephen Gallagher - 1.1.1-1 +- Update to version 1.1.1 +- Make default stream and profiles optional +- Fixes: https://github.com/fedora-modularity/libmodulemd/issues/25 +- Fixes: https://github.com/fedora-modularity/libmodulemd/issues/26 +- Fixes: https://github.com/fedora-modularity/libmodulemd/issues/27 + +* Wed Mar 14 2018 Stephen Gallagher - 1.1.0-1 +- Update to version 1.1.0 +- Adds support for handling modulemd-defaults YAML documents +- Adds peek()/dup() routines to all object properties +- Adds Modulemd.Module.dup_nsvc() to retrieve the canonical form of the unique module identifier. +- Adds support for boolean types in the XMD section +- Revert obsoletion of pythonX-modulemd packages for now + +* Tue Mar 13 2018 Igor Gnatenko - 1.0.4-2 +- Obsolete unsupported pythonX-modulemd packages + +* Tue Feb 27 2018 Stephen Gallagher - 1.0.4-1 +- Update to 1.0.4 +- Rework version autodetection +- Avoid infinite loop on unparseable YAML + +* Sun Feb 25 2018 Stephen Gallagher - 1.0.3-1 +- RPM components are properly emitted when no module components exist +- Parser works around late determination of modulemd version + +* Fri Feb 16 2018 Stephen Gallagher - 1.0.2-1 +- Be more strict with certain parser edge-cases +- Replace popt argument processing with glib +- Drop upstreamed patches + +* Thu Feb 15 2018 Stephen Gallagher - 1.0.1-2 +- Handle certain unlikely format violations + +* Thu Feb 15 2018 Stephen Gallagher - 1.0.1-1 +- Support modulemd v2 +- Add tool to do quick validation of modulemd +- Fix memory management +- Warn and ignore unparseable sub-documents in the YAML +- Fix several memory issues detected by Coverity scan + +* Tue Feb 06 2018 Stephen Gallagher - 0.2.2-1 +- Update to libmodulemd 0.2.2 +- Fix numerous minor memory leaks +- Fix issues with EOL/SL dates + +* Tue Feb 06 2018 Igor Gnatenko - 0.2.1-3 +- Own appropriate directories + +* Fri Feb 02 2018 Igor Gnatenko - 0.2.1-2 +- Switch to %%ldconfig_scriptlets + +* Fri Jan 05 2018 Stephen Gallagher - 0.2.1-1 +- Update to libmodulemd 0.2.1 +- Add 'name' property for Profiles + +* Thu Oct 05 2017 Stephen Gallagher - 0.2.0-2 +- Add missing BuildRequires for gtk-doc + +* Thu Oct 05 2017 Stephen Gallagher - 0.2.0-1 +- Update to libmodulemd 0.2.0 +- Adds gtk-doc generated documentation +- (ABI-break) Makes all optional properties accept NULL as a value to clear + them +- (ABI-break) Modulemd.SimpleSet takes a STRV (char **) instead of a + GLib.PtrArray +- Fixes a bug where the name was not always set for components +- Adds support for dumping YAML from the introspected API +- Includes add/remove routines for profiles + +* Sat Sep 30 2017 Igor Gnatenko - 0.1.0-5 +- Use %%_isa in Requires for main package from devel + +* Mon Sep 18 2017 Stephen Gallagher - 0.1.0-4 +- Correct the license to MIT + +* Mon Sep 18 2017 Stephen Gallagher - 0.1.0-3 +- Modifications requested during package review + +* Fri Sep 15 2017 Stephen Gallagher - 0.1.0-2 +- First public release +