Skip to content

Commit 2000e88

Browse files
committed
Add static_context attribute to StreamV2
Signed-off-by: Stephen Gallagher <[email protected]>
1 parent 8970449 commit 2000e88

File tree

7 files changed

+359
-5
lines changed

7 files changed

+359
-5
lines changed

modulemd/include/modulemd-2.0/modulemd-module-stream-v2.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,4 +904,42 @@ GVariant *
904904
modulemd_module_stream_v2_get_xmd (ModulemdModuleStreamV2 *self);
905905

906906

907+
/**
908+
* modulemd_module_stream_v2_set_static_context:
909+
* @self: (in): This #ModulemdModuleStreamV2 object.
910+
*
911+
* Marks this #ModulemdModuleStreamV2 to indicate to dependency solvers that
912+
* they must treat the `context` attribute as informative.
913+
*
914+
* Since: 2.11
915+
*/
916+
void
917+
modulemd_module_stream_v2_set_static_context (ModulemdModuleStreamV2 *self);
918+
919+
920+
/**
921+
* modulemd_module_stream_v2_unset_static_context:
922+
* @self: (in): This #ModulemdModuleStreamV2 object.
923+
*
924+
* Marks this #ModulemdModuleStreamV2 to indicate to dependency solvers that
925+
* they must ignore the `context` attribute as a uniqueness element.
926+
*
927+
* Since: 2.11
928+
*/
929+
void
930+
modulemd_module_stream_v2_unset_static_context (ModulemdModuleStreamV2 *self);
931+
932+
933+
/**
934+
* modulemd_module_stream_v2_is_static_context:
935+
* @self: (in): This #ModulemdModuleStreamV2 object.
936+
*
937+
* Returns: Whether the `context` attribute should be treated as static.
938+
*
939+
* Since: 2.11
940+
*/
941+
gboolean
942+
modulemd_module_stream_v2_is_static_context (ModulemdModuleStreamV2 *self);
943+
944+
907945
G_END_DECLS

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ struct _ModulemdModuleStreamV2
6868
ModulemdObsoletes *obsoletes;
6969

7070
GVariant *xmd;
71+
72+
gboolean static_context;
7173
};
7274

7375

modulemd/modulemd-docs.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@
146146
<title>2.10 API Index</title>
147147
<xi:include href="xml/api-index-2.10.xml"/>
148148
</chapter>
149+
<chapter>
150+
<title>2.11 API Index</title>
151+
<xi:include href="xml/api-index-2.11.xml"/>
152+
</chapter>
149153
<chapter>
150154
<title>Deprecated API Index</title>
151155
<xi:include href="xml/api-index-deprecated.xml"/>

modulemd/modulemd-module-stream-v2.c

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ enum
4949
PROP_COMMUNITY,
5050
PROP_DOCUMENTATION,
5151
PROP_TRACKER,
52+
PROP_STATIC_CONTEXT,
5253
N_PROPS
5354
};
5455

@@ -1196,6 +1197,72 @@ modulemd_module_stream_v2_includes_nevra (ModulemdModuleStreamV2 *self,
11961197
}
11971198

11981199

1200+
void
1201+
modulemd_module_stream_v2_set_static_context (ModulemdModuleStreamV2 *self)
1202+
{
1203+
self->static_context = TRUE;
1204+
1205+
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATIC_CONTEXT]);
1206+
}
1207+
1208+
1209+
void
1210+
modulemd_module_stream_v2_unset_static_context (ModulemdModuleStreamV2 *self)
1211+
{
1212+
self->static_context = FALSE;
1213+
1214+
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATIC_CONTEXT]);
1215+
}
1216+
1217+
1218+
gboolean
1219+
modulemd_module_stream_v2_is_static_context (ModulemdModuleStreamV2 *self)
1220+
{
1221+
return self->static_context;
1222+
}
1223+
1224+
1225+
static gboolean
1226+
modulemd_module_stream_v2_validate_context (const gchar *context,
1227+
GError **error)
1228+
{
1229+
/* must be string of up to MMD_MAXCONTEXTLEN [a-zA-Z0-9] */
1230+
1231+
if (context == NULL || *context == '\0')
1232+
{
1233+
g_set_error (
1234+
error, MODULEMD_ERROR, MMD_ERROR_VALIDATE, "Empty stream context");
1235+
return FALSE;
1236+
}
1237+
1238+
if (strlen (context) > MMD_MAXCONTEXTLEN)
1239+
{
1240+
g_set_error (error,
1241+
MODULEMD_ERROR,
1242+
MMD_ERROR_VALIDATE,
1243+
"Stream context '%s' exceeds maximum length (%d)",
1244+
context,
1245+
MMD_MAXCONTEXTLEN);
1246+
return FALSE;
1247+
}
1248+
1249+
for (const gchar *i = context; *i != '\0'; i++)
1250+
{
1251+
if (!g_ascii_isalnum (*i))
1252+
{
1253+
g_set_error (error,
1254+
MODULEMD_ERROR,
1255+
MMD_ERROR_VALIDATE,
1256+
"Non-alphanumeric character in stream context '%s'",
1257+
context);
1258+
return FALSE;
1259+
}
1260+
}
1261+
1262+
return TRUE;
1263+
}
1264+
1265+
11991266
static gboolean
12001267
modulemd_module_stream_v2_validate (ModulemdModuleStream *self, GError **error)
12011268
{
@@ -1207,6 +1274,7 @@ modulemd_module_stream_v2_validate (ModulemdModuleStream *self, GError **error)
12071274
ModulemdDependencies *deps = NULL;
12081275
g_autoptr (GError) nested_error = NULL;
12091276
g_auto (GStrv) buildopts_arches = NULL;
1277+
const gchar *context = NULL;
12101278

12111279
g_return_val_if_fail (MODULEMD_IS_MODULE_STREAM_V2 (self), FALSE);
12121280
v2_self = MODULEMD_MODULE_STREAM_V2 (self);
@@ -1217,6 +1285,22 @@ modulemd_module_stream_v2_validate (ModulemdModuleStream *self, GError **error)
12171285
return FALSE;
12181286
}
12191287

1288+
/* Validate static context if present */
1289+
if (v2_self->static_context)
1290+
{
1291+
context =
1292+
modulemd_module_stream_get_context (MODULEMD_MODULE_STREAM (self));
1293+
if (context)
1294+
{
1295+
if (!modulemd_module_stream_v2_validate_context (context,
1296+
&nested_error))
1297+
{
1298+
g_propagate_error (error, g_steal_pointer (&nested_error));
1299+
return FALSE;
1300+
}
1301+
}
1302+
}
1303+
12201304
/* Make sure that mandatory fields are present */
12211305
if (!modulemd_module_stream_v2_get_summary (v2_self, "C"))
12221306
{
@@ -1339,6 +1423,11 @@ modulemd_module_stream_v2_get_property (GObject *object,
13391423
g_value_set_string (value, modulemd_module_stream_v2_get_tracker (self));
13401424
break;
13411425

1426+
case PROP_STATIC_CONTEXT:
1427+
g_value_set_boolean (value,
1428+
modulemd_module_stream_v2_is_static_context (self));
1429+
break;
1430+
13421431
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
13431432
}
13441433
}
@@ -1375,6 +1464,17 @@ modulemd_module_stream_v2_set_property (GObject *object,
13751464
modulemd_module_stream_v2_set_tracker (self, g_value_get_string (value));
13761465
break;
13771466

1467+
case PROP_STATIC_CONTEXT:
1468+
if (g_value_get_boolean (value))
1469+
{
1470+
modulemd_module_stream_v2_set_static_context (self);
1471+
}
1472+
else
1473+
{
1474+
modulemd_module_stream_v2_unset_static_context (self);
1475+
}
1476+
break;
1477+
13781478
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
13791479
}
13801480
}
@@ -1431,6 +1531,7 @@ modulemd_module_stream_v2_copy (ModulemdModuleStream *self,
14311531
STREAM_COPY_IF_SET (v2, copy, v2_self, documentation);
14321532
STREAM_COPY_IF_SET_WITH_LOCALE (v2, copy, v2_self, summary);
14331533
STREAM_COPY_IF_SET (v2, copy, v2_self, tracker);
1534+
copy->static_context = v2_self->static_context;
14341535

14351536
/* Internal Data Structures: With replace function */
14361537
STREAM_REPLACE_HASHTABLE (v2, copy, v2_self, content_licenses);
@@ -1577,6 +1678,13 @@ modulemd_module_stream_v2_class_init (ModulemdModuleStreamV2Class *klass)
15771678
NULL,
15781679
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
15791680

1681+
properties[PROP_STATIC_CONTEXT] =
1682+
g_param_spec_boolean ("static-context",
1683+
"Static Context",
1684+
"Whether the context is static",
1685+
0,
1686+
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
1687+
15801688
g_object_class_install_properties (object_class, N_PROPS, properties);
15811689
}
15821690

@@ -1686,6 +1794,7 @@ modulemd_module_stream_v2_parse_yaml (ModulemdSubdocumentInfo *subdoc,
16861794
g_autoptr (ModulemdBuildopts) buildopts = NULL;
16871795
g_autoptr (GVariant) xmd = NULL;
16881796
guint64 version;
1797+
gboolean static_context;
16891798

16901799
if (!modulemd_subdocument_info_get_data_parser (
16911800
subdoc, &parser, strict, error))
@@ -1768,6 +1877,28 @@ modulemd_module_stream_v2_parse_yaml (ModulemdSubdocumentInfo *subdoc,
17681877
MODULEMD_MODULE_STREAM (modulestream));
17691878
}
17701879

1880+
else if (g_str_equal ((const gchar *)event.data.scalar.value,
1881+
"static_context"))
1882+
{
1883+
static_context =
1884+
modulemd_yaml_parse_bool (&parser, &nested_error);
1885+
if (nested_error)
1886+
{
1887+
g_propagate_error (error, g_steal_pointer (&nested_error));
1888+
return NULL;
1889+
}
1890+
1891+
if (static_context)
1892+
{
1893+
modulemd_module_stream_v2_set_static_context (modulestream);
1894+
}
1895+
else
1896+
{
1897+
modulemd_module_stream_v2_unset_static_context (
1898+
modulestream);
1899+
}
1900+
}
1901+
17711902
/* Module Artifact Architecture */
17721903
else if (g_str_equal ((const gchar *)event.data.scalar.value,
17731904
"arch") &&
@@ -2856,6 +2987,11 @@ modulemd_module_stream_v2_emit_yaml (ModulemdModuleStreamV2 *self,
28562987
return FALSE;
28572988
}
28582989

2990+
if (modulemd_module_stream_v2_is_static_context (self))
2991+
{
2992+
EMIT_KEY_VALUE (emitter, error, "static_context", "true");
2993+
}
2994+
28592995
EMIT_KEY_VALUE_IF_SET (
28602996
emitter, error, "arch", modulemd_module_stream_v2_get_arch (self));
28612997
EMIT_KEY_VALUE (emitter, error, "summary", self->summary);

modulemd/tests/ModulemdTests/modulestream.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,6 +1426,108 @@ def test_search_profiles(self):
14261426
self.assertIsInstance(profiles[2], Modulemd.Profile)
14271427
self.assertEqual(profiles[2].get_name(), "thethirdprofile")
14281428

1429+
def test_static_context(self):
1430+
stream = Modulemd.ModuleStreamV2.new("themodule", "thestream")
1431+
1432+
# Verify that it defaults to FALSE
1433+
self.assertFalse(stream.props.static_context)
1434+
self.assertFalse(stream.is_static_context())
1435+
1436+
# Test setting and unsetting it via methods
1437+
stream.set_static_context()
1438+
self.assertTrue(stream.props.static_context)
1439+
self.assertTrue(stream.is_static_context())
1440+
1441+
stream.unset_static_context()
1442+
self.assertFalse(stream.props.static_context)
1443+
self.assertFalse(stream.is_static_context())
1444+
1445+
# Test setting and unsetting it via properties
1446+
stream.props.static_context = True
1447+
self.assertTrue(stream.props.static_context)
1448+
self.assertTrue(stream.is_static_context())
1449+
1450+
stream.props.static_context = False
1451+
self.assertFalse(stream.props.static_context)
1452+
self.assertFalse(stream.is_static_context())
1453+
1454+
# Read in a stream with a static context
1455+
idx = Modulemd.load_file(
1456+
"%s/static_context.yaml" % (os.getenv("TEST_DATA_PATH"))
1457+
)
1458+
streams = idx.search_streams()
1459+
self.assertEquals(1, len(streams))
1460+
stream = streams[0]
1461+
self.assertTrue(stream.props.static_context)
1462+
self.assertTrue(stream.is_static_context())
1463+
1464+
expected = """---
1465+
document: modulemd
1466+
version: 2
1467+
data:
1468+
name: nodejs
1469+
stream: "8"
1470+
version: 20180816123422
1471+
context: RealCTX
1472+
static_context: true
1473+
arch: x86_64
1474+
summary: Javascript runtime
1475+
description: >-
1476+
Node.js is a platform built on Chrome''s JavaScript runtime for easily building
1477+
fast, scalable network applications. Node.js uses an event-driven, non-blocking
1478+
I/O model that makes it lightweight and efficient, perfect for data-intensive
1479+
real-time applications that run across distributed devices.
1480+
license:
1481+
module:
1482+
- MIT
1483+
content:
1484+
- MIT and ASL 2.0 and ISC and BSD
1485+
dependencies:
1486+
- buildrequires:
1487+
platform: [f29]
1488+
requires:
1489+
platform: [f29]
1490+
references:
1491+
community: http://nodejs.org
1492+
documentation: http://nodejs.org/en/docs
1493+
tracker: https://github.com/nodejs/node/issues
1494+
profiles:
1495+
default:
1496+
rpms:
1497+
- nodejs
1498+
- npm
1499+
development:
1500+
rpms:
1501+
- nodejs
1502+
- nodejs-devel
1503+
- npm
1504+
minimal:
1505+
rpms:
1506+
- nodejs
1507+
api:
1508+
rpms:
1509+
- nodejs
1510+
- nodejs-devel
1511+
- npm
1512+
components:
1513+
rpms:
1514+
nodejs:
1515+
rationale: Javascript runtime and npm package manager.
1516+
repository: git://pkgs.fedoraproject.org/rpms/nodejs
1517+
cache: http://pkgs.fedoraproject.org/repo/pkgs/nodejs
1518+
ref: 8
1519+
buildorder: 10
1520+
artifacts:
1521+
rpms:
1522+
- nodejs-1:8.11.4-1.module_2030+42747d40.x86_64
1523+
- nodejs-devel-1:8.11.4-1.module_2030+42747d40.x86_64
1524+
- nodejs-docs-1:8.11.4-1.module_2030+42747d40.noarch
1525+
- npm-1:5.6.0-1.8.11.4.1.module_2030+42747d40.x86_64
1526+
...
1527+
"""
1528+
self.maxDiff = None
1529+
self.assertEquals(expected, idx.dump_to_string())
1530+
14291531

14301532
if __name__ == "__main__":
14311533
unittest.main()

0 commit comments

Comments
 (0)