Skip to content

Commit 82cbe08

Browse files
committed
Merge branch 'defaults-stream-conflict'
2 parents 3f11316 + 507ff3d commit 82cbe08

File tree

9 files changed

+180
-46
lines changed

9 files changed

+180
-46
lines changed

modulemd/v1/include/modulemd-1.0/private/modulemd-private.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ enum
2626

2727
#define MD_VERSION_LATEST MD_VERSION_2
2828

29+
#define DEFAULT_MERGE_CONFLICT "__merge_conflict__"
30+
2931
ModulemdModule *
3032
modulemd_module_new_from_modulestream (ModulemdModuleStream *stream);
3133

modulemd/v1/modulemd-defaults.c

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "modulemd.h"
1515
#include "modulemd-defaults.h"
1616
#include "modulemd-simpleset.h"
17+
#include "private/modulemd-private.h"
1718
#include "private/modulemd-yaml.h"
1819

1920

@@ -148,6 +149,15 @@ modulemd_defaults_peek_default_stream (ModulemdDefaults *self)
148149
{
149150
g_return_val_if_fail (self, NULL);
150151

152+
if (self->default_stream &&
153+
g_str_equal (self->default_stream, DEFAULT_MERGE_CONFLICT))
154+
{
155+
/* During an index merge, we determined that this was in conflict
156+
* with another set of ModulemdDefaults for the same module. If we
157+
* see this, treat it as no default stream when querying for it.
158+
*/
159+
return NULL;
160+
}
151161
return self->default_stream;
152162
}
153163

@@ -157,6 +167,16 @@ modulemd_defaults_dup_default_stream (ModulemdDefaults *self)
157167
{
158168
g_return_val_if_fail (self, NULL);
159169

170+
if (self->default_stream &&
171+
g_str_equal (self->default_stream, DEFAULT_MERGE_CONFLICT))
172+
{
173+
/* During an index merge, we determined that this was in conflict
174+
* with another set of ModulemdDefaults for the same module. If we
175+
* see this, treat it as no default stream when querying for it.
176+
*/
177+
return NULL;
178+
}
179+
160180
return g_strdup (self->default_stream);
161181
}
162182

@@ -755,24 +775,21 @@ modulemd_defaults_merge (ModulemdDefaults *first,
755775
* Merge them as best we can.
756776
*/
757777

778+
defaults = modulemd_defaults_copy (first);
779+
758780
/* First check for incompatibilities with the streams */
759-
if (g_strcmp0 (modulemd_defaults_peek_default_stream (first),
760-
modulemd_defaults_peek_default_stream (second)))
781+
if (g_strcmp0 (first->default_stream, second->default_stream))
761782
{
762783
/* Default streams don't match and override is not set.
763784
* Return an error
764785
*/
765-
g_set_error (
766-
error,
767-
MODULEMD_DEFAULTS_ERROR,
768-
MODULEMD_DEFAULTS_ERROR_CONFLICTING_STREAMS,
769-
"Conflicting default streams when merging defaults for module %s",
770-
modulemd_defaults_peek_module_name (first));
771-
return NULL;
786+
/* They have conflicting default streams */
787+
g_info ("Module stream mismatch in merge: %s != %s",
788+
first->default_stream,
789+
second->default_stream);
790+
modulemd_defaults_set_default_stream (defaults, DEFAULT_MERGE_CONFLICT);
772791
}
773792

774-
defaults = modulemd_defaults_copy (first);
775-
776793
/* Merge the profile defaults */
777794
profile_defaults = modulemd_defaults_peek_profile_defaults (defaults);
778795

modulemd/v1/tests/test-modulemd-defaults.c

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ modulemd_defaults_test_prioritizer (DefaultsFixture *fixture,
604604
g_autofree gchar *yaml_override_path = NULL;
605605
g_autoptr (GPtrArray) base_objects = NULL;
606606
g_autoptr (GPtrArray) override_objects = NULL;
607+
g_autoptr (GPtrArray) override_nodejs_objects = NULL;
607608
g_autoptr (GPtrArray) merged_objects = NULL;
608609
g_autoptr (ModulemdPrioritizer) prioritizer = NULL;
609610
g_autoptr (GError) error = NULL;
@@ -620,6 +621,18 @@ modulemd_defaults_test_prioritizer (DefaultsFixture *fixture,
620621
g_assert_nonnull (base_objects);
621622
g_assert_cmpint (base_objects->len, ==, 7);
622623

624+
625+
yaml_override_path =
626+
g_strdup_printf ("%s/test_data/defaults/overriding-nodejs.yaml",
627+
g_getenv ("MESON_SOURCE_ROOT"));
628+
g_assert_nonnull (yaml_override_path);
629+
630+
override_nodejs_objects =
631+
modulemd_objects_from_file (yaml_override_path, &error);
632+
g_clear_pointer (&yaml_override_path, g_free);
633+
g_assert_nonnull (override_nodejs_objects);
634+
g_assert_cmpint (override_nodejs_objects->len, ==, 1);
635+
623636
yaml_override_path = g_strdup_printf (
624637
"%s/test_data/defaults/overriding.yaml", g_getenv ("MESON_SOURCE_ROOT"));
625638
g_assert_nonnull (yaml_override_path);
@@ -661,6 +674,48 @@ modulemd_defaults_test_prioritizer (DefaultsFixture *fixture,
661674
g_assert_true (result);
662675

663676

677+
/*
678+
* Test that importing the nodejs overrides at the same priority level fails.
679+
*
680+
* This YAML has a conflicting default stream which should be ignored and set
681+
* to "no default stream".
682+
*/
683+
684+
result = modulemd_prioritizer_add (
685+
prioritizer, override_nodejs_objects, prio, &error);
686+
g_assert_true (result);
687+
688+
merged_objects = modulemd_prioritizer_resolve (prioritizer, &error);
689+
g_assert_nonnull (merged_objects);
690+
g_assert_cmpint (merged_objects->len, ==, 3);
691+
692+
for (gint i = 0; i < merged_objects->len; i++)
693+
{
694+
if (MODULEMD_IS_DEFAULTS (g_ptr_array_index (merged_objects, i)))
695+
{
696+
defaults = g_ptr_array_index (merged_objects, i);
697+
if (!g_strcmp0 (modulemd_defaults_peek_module_name (defaults),
698+
"nodejs"))
699+
{
700+
g_assert_null (modulemd_defaults_peek_default_stream (defaults));
701+
}
702+
}
703+
}
704+
705+
g_clear_pointer (&merged_objects, g_ptr_array_unref);
706+
707+
708+
/* Start over and test profile conflicts */
709+
g_clear_pointer (&prioritizer, g_object_unref);
710+
prioritizer = modulemd_prioritizer_new ();
711+
result = modulemd_prioritizer_add (prioritizer, base_objects, prio, &error);
712+
if (!result)
713+
{
714+
fprintf (stderr, "Merge error: %s", error->message);
715+
}
716+
g_assert_true (result);
717+
718+
664719
/*
665720
* Test that importing the overrides at the same priority level fails.
666721
*
@@ -673,7 +728,7 @@ modulemd_defaults_test_prioritizer (DefaultsFixture *fixture,
673728
g_assert_cmpstr (
674729
g_quark_to_string (error->domain), ==, "modulemd-defaults-error-quark");
675730
g_assert_cmpint (
676-
error->code, ==, MODULEMD_DEFAULTS_ERROR_CONFLICTING_STREAMS);
731+
error->code, ==, MODULEMD_DEFAULTS_ERROR_CONFLICTING_PROFILES);
677732
g_clear_pointer (&error, g_error_free);
678733

679734
/* The object's internal state is undefined after an error, so delete it */
@@ -989,7 +1044,7 @@ modulemd_defaults_test_index_prioritizer (DefaultsFixture *fixture,
9891044
g_assert_cmpstr (
9901045
g_quark_to_string (error->domain), ==, "modulemd-defaults-error-quark");
9911046
g_assert_cmpint (
992-
error->code, ==, MODULEMD_DEFAULTS_ERROR_CONFLICTING_STREAMS);
1047+
error->code, ==, MODULEMD_DEFAULTS_ERROR_CONFLICTING_PROFILES);
9931048
g_clear_pointer (&error, g_error_free);
9941049

9951050
/* The object's internal state is undefined after an error, so delete it */
@@ -1140,6 +1195,11 @@ modulemd_regressions_issue44 (DefaultsFixture *fixture,
11401195

11411196
/* Add another almost-identical document, except with a conflicting default
11421197
* stream set.
1198+
*
1199+
* NOTE: when this was written (for issue 44 on GitHub), this was meant to be
1200+
* a hard error. As of 1.8.1 we expect this to just result in having no
1201+
* default stream for this module. This test has been slightly modified so
1202+
* that the expected result is now a pass.
11431203
*/
11441204
yaml_conflicting_path = g_strdup_printf (
11451205
"%s/test_data/defaults/issue44-2.yaml", g_getenv ("MESON_SOURCE_ROOT"));
@@ -1151,7 +1211,7 @@ modulemd_regressions_issue44 (DefaultsFixture *fixture,
11511211

11521212
result =
11531213
modulemd_prioritizer_add (prioritizer, conflicting_objects, 0, &error);
1154-
g_assert_false (result);
1214+
g_assert_true (result);
11551215
}
11561216

11571217

modulemd/v2/include/modulemd-2.0/modulemd-module-index-merger.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ G_BEGIN_DECLS
7171
* it.
7272
* - If either repository specifies a default stream for the module and the
7373
* other does not, use the one specified.
74-
* - If both repositories specify different streams, this is an unresolvable
75-
* merge conflict and the merge resolution will fail and report an error.
74+
* - If both repositories specify different default streams, the merge will
75+
* unset the default stream and proceed with the merge.
7676
* - If both repositories specify a set of default profiles for a stream and
7777
* the sets are equivalent, use that set.
7878
* - If one repository specifies a set of default profiles for a stream and

modulemd/v2/include/modulemd-2.0/private/modulemd-defaults-v1-private.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ G_BEGIN_DECLS
2828
* internal consumers.
2929
*/
3030

31+
#define DEFAULT_MERGE_CONFLICT "__merge_conflict__"
32+
3133
/**
3234
* modulemd_defaults_v1_parse_yaml:
3335
* @subdoc: (in): A #ModulemdSubdocumentInfo representing a defaults document

modulemd/v2/modulemd-defaults-v1.c

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,18 @@ modulemd_defaults_v1_get_default_stream (ModulemdDefaultsV1 *self,
181181
g_return_val_if_fail (MODULEMD_IS_DEFAULTS_V1 (self), NULL);
182182

183183
if (!intent)
184-
return self->default_stream;
184+
{
185+
if (self->default_stream &&
186+
g_str_equal (self->default_stream, DEFAULT_MERGE_CONFLICT))
187+
{
188+
/* During an index merge, we determined that this was in conflict
189+
* with another set of ModulemdDefaults for the same module. If we
190+
* see this, treat it as no default stream when querying for it.
191+
*/
192+
return NULL;
193+
}
194+
return self->default_stream;
195+
}
185196

186197
default_stream = g_hash_table_lookup (self->intent_default_streams, intent);
187198
if (default_stream)
@@ -1144,8 +1155,6 @@ modulemd_defaults_v1_merge (const gchar *module_name,
11441155
ModulemdDefaultsV1 *into,
11451156
GError **error)
11461157
{
1147-
const gchar *into_default_stream;
1148-
const gchar *from_default_stream;
11491158
g_autoptr (ModulemdDefaultsV1) merged = NULL;
11501159
GHashTableIter iter;
11511160
gpointer key, value;
@@ -1160,33 +1169,41 @@ modulemd_defaults_v1_merge (const gchar *module_name,
11601169
merged = modulemd_defaults_v1_new (module_name);
11611170

11621171
/* Merge the default streams */
1163-
into_default_stream = modulemd_defaults_v1_get_default_stream (into, NULL);
1164-
from_default_stream = modulemd_defaults_v1_get_default_stream (from, NULL);
1165-
1166-
if (into_default_stream && !from_default_stream)
1172+
if (into->default_stream && !from->default_stream)
11671173
{
11681174
modulemd_defaults_v1_set_default_stream (
1169-
merged, into_default_stream, NULL);
1175+
merged, into->default_stream, NULL);
11701176
}
1171-
else if (from_default_stream && !into_default_stream)
1177+
else if (from->default_stream && !into->default_stream)
11721178
{
11731179
modulemd_defaults_v1_set_default_stream (
1174-
merged, from_default_stream, NULL);
1180+
merged, from->default_stream, NULL);
11751181
}
1176-
else if (into_default_stream && from_default_stream)
1182+
else if (into->default_stream && from->default_stream)
11771183
{
1178-
if (!g_str_equal (into_default_stream, from_default_stream))
1184+
if (g_str_equal (into->default_stream, DEFAULT_MERGE_CONFLICT))
11791185
{
1180-
g_set_error (error,
1181-
MODULEMD_ERROR,
1182-
MODULEMD_ERROR_VALIDATE,
1183-
"Module stream mismatch in merge: %s != %s",
1184-
into_default_stream,
1185-
from_default_stream);
1186-
return NULL;
1186+
/* A previous pass over this same module encountered a merge
1187+
* conflict, so we need to propagate that.
1188+
*/
1189+
modulemd_defaults_v1_set_default_stream (
1190+
merged, DEFAULT_MERGE_CONFLICT, NULL);
1191+
}
1192+
else if (!g_str_equal (into->default_stream, from->default_stream))
1193+
{
1194+
/* They have conflicting default streams */
1195+
g_info ("Module stream mismatch in merge: %s != %s",
1196+
into->default_stream,
1197+
from->default_stream);
1198+
modulemd_defaults_v1_set_default_stream (
1199+
merged, DEFAULT_MERGE_CONFLICT, NULL);
1200+
}
1201+
else
1202+
{
1203+
/* They're the same, so store that */
1204+
modulemd_defaults_v1_set_default_stream (
1205+
merged, into->default_stream, NULL);
11871206
}
1188-
modulemd_defaults_v1_set_default_stream (
1189-
merged, into_default_stream, NULL);
11901207
}
11911208
else
11921209
{

modulemd/v2/tests/ModulemdTests/merger.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,21 +106,36 @@ def test_merger(self):
106106
self.assertEqual(
107107
len(httpd_defaults.get_default_profiles_for_stream('2.6', 'workstation')), 3)
108108

109-
# Get another set of objects that will override the above
110-
override_index = Modulemd.ModuleIndex()
111-
override_index.update_from_file(
109+
# Get another set of objects that will override the default stream for
110+
# nodejs
111+
override_nodejs_index = Modulemd.ModuleIndex()
112+
override_nodejs_index.update_from_file(
112113
path.join(
113114
self.source_root,
114-
"modulemd/v2/tests/test_data/overriding.yaml"), True)
115+
"modulemd/v2/tests/test_data/overriding-nodejs.yaml"), True)
115116

116-
# Test that adding both of these at the same priority level fails
117-
# with a merge conflict.
117+
# Test that adding both of these at the same priority level results in
118+
# the no default stream
118119
merger = Modulemd.ModuleIndexMerger()
119120
merger.associate_index(base_index, 0)
120-
merger.associate_index(override_index, 0)
121+
merger.associate_index(override_nodejs_index, 0)
122+
123+
merged_index = merger.resolve()
124+
self.assertIsNotNone(merged_index)
121125

122-
with self.assertRaisesRegex(GLib.GError, 'Module stream mismatch in merge'):
123-
merged_index = merger.resolve()
126+
nodejs = merged_index.get_module('nodejs')
127+
self.assertIsNotNone(nodejs)
128+
129+
nodejs_defaults = nodejs.get_defaults()
130+
self.assertIsNotNone(nodejs_defaults)
131+
self.assertIsNone(nodejs_defaults.get_default_stream())
132+
133+
# Get another set of objects that will override the above
134+
override_index = Modulemd.ModuleIndex()
135+
override_index.update_from_file(
136+
path.join(
137+
self.source_root,
138+
"modulemd/v2/tests/test_data/overriding.yaml"), True)
124139

125140
# Test that override_index at a higher priority level succeeds
126141
# Test that adding both of these at the same priority level fails
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
# Override the default stream
3+
document: modulemd-defaults
4+
version: 1
5+
data:
6+
module: nodejs
7+
stream: '9.0'
8+
profiles:
9+
'6.0': [default]
10+
'8.0': [super]
11+
'9.0': [supermegaultra]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
document: modulemd-defaults
3+
version: 1
4+
data:
5+
module: nodejs
6+
stream: '9.0'
7+
profiles:
8+
'6.0': [default]
9+
'8.0': [super]
10+
'9.0': [supermegaultra]

0 commit comments

Comments
 (0)