[gnome-software: 2/6] gs-appstream: Implement requires/recommends
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software: 2/6] gs-appstream: Implement requires/recommends
- Date: Wed, 30 Jun 2021 12:48:14 +0000 (UTC)
commit aff48d39372c031b3d5dd29a94fec3d1a14e5951
Author: Philip Withnall <pwithnall endlessos org>
Date: Tue Jun 22 14:38:16 2021 +0100
gs-appstream: Implement requires/recommends
Signed-off-by: Philip Withnall <pwithnall endlessos org>
lib/gs-appstream.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 109 insertions(+)
---
diff --git a/lib/gs-appstream.c b/lib/gs-appstream.c
index 717a26bbf..c7c165b3c 100644
--- a/lib/gs-appstream.c
+++ b/lib/gs-appstream.c
@@ -737,6 +737,105 @@ gs_appstream_refine_app_content_ratings (GsApp *app,
return TRUE;
}
+static gboolean
+gs_appstream_refine_app_relation (GsPlugin *plugin,
+ GsApp *app,
+ XbNode *relation_node,
+ AsRelationKind kind,
+ GError **error)
+{
+ /* Iterate over the children, which might be any combination of zero or
+ * more <id/>, <modalias/>, <kernel/>, <memory/>, <firmware/>,
+ * <control/> or <display_length/> elements. For the moment, we only
+ * support some of these. */
+ for (g_autoptr(XbNode) child = xb_node_get_child (relation_node); child != NULL; child =
xb_node_get_next (child)) {
+ const gchar *item_kind = xb_node_get_element (child);
+ g_autoptr(AsRelation) relation = as_relation_new ();
+
+ as_relation_set_kind (relation, kind);
+
+ if (g_str_equal (item_kind, "control")) {
+ /*
https://www.freedesktop.org/software/appstream/docs/chap-Metadata.html#tag-requires-recommends-control */
+ as_relation_set_item_kind (relation, AS_RELATION_ITEM_KIND_CONTROL);
+ as_relation_set_value_control_kind (relation, as_control_kind_from_string
(xb_node_get_text (child)));
+ } else if (g_str_equal (item_kind, "display_length")) {
+ AsDisplayLengthKind display_length_kind;
+ const gchar *compare;
+
+ /*
https://www.freedesktop.org/software/appstream/docs/chap-Metadata.html#tag-requires-recommends-display_length
*/
+ as_relation_set_item_kind (relation, AS_RELATION_ITEM_KIND_DISPLAY_LENGTH);
+
+ compare = xb_node_get_attr (child, "compare");
+ as_relation_set_compare (relation, (compare != NULL) ?
as_relation_compare_from_string (compare) : AS_RELATION_COMPARE_GE);
+
+ display_length_kind = as_display_length_kind_from_string (xb_node_get_text (child));
+ if (display_length_kind != AS_DISPLAY_LENGTH_KIND_UNKNOWN) {
+ /* Ignore the `side` attribute */
+ as_relation_set_value_display_length_kind (relation, display_length_kind);
+ } else {
+ const gchar *side = xb_node_get_attr (child, "side");
+ as_relation_set_display_side_kind (relation, (side != NULL) ?
as_display_side_kind_from_string (side) : AS_DISPLAY_SIDE_KIND_SHORTEST);
+ as_relation_set_value_px (relation, xb_node_get_text_as_uint (child));
+ }
+ } else {
+ g_debug ("Relation type ā%sā not currently supported for %s; ignoring",
+ item_kind, gs_app_get_id (app));
+ continue;
+ }
+
+ gs_app_add_relation (app, relation);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gs_appstream_refine_app_relations (GsPlugin *plugin,
+ GsApp *app,
+ XbNode *component,
+ GError **error)
+{
+ g_autoptr(GPtrArray) recommends = NULL;
+ g_autoptr(GPtrArray) requires = NULL;
+ g_autoptr(GError) error_local = NULL;
+
+ /* find any recommends */
+ recommends = xb_node_query (component, "recommends", 0, &error_local);
+ if (recommends == NULL) {
+ if (g_error_matches (error_local, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ return TRUE;
+ if (g_error_matches (error_local, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT))
+ return TRUE;
+ g_propagate_error (error, g_steal_pointer (&error_local));
+ return FALSE;
+ }
+
+ for (guint i = 0; i < recommends->len; i++) {
+ XbNode *recommend = g_ptr_array_index (recommends, i);
+ if (!gs_appstream_refine_app_relation (plugin, app, recommend, AS_RELATION_KIND_RECOMMENDS,
error))
+ return FALSE;
+ }
+
+ /* find any requires */
+ requires = xb_node_query (component, "requires", 0, &error_local);
+ if (requires == NULL) {
+ if (g_error_matches (error_local, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ return TRUE;
+ if (g_error_matches (error_local, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT))
+ return TRUE;
+ g_propagate_error (error, g_steal_pointer (&error_local));
+ return FALSE;
+ }
+
+ for (guint i = 0; i < requires->len; i++) {
+ XbNode *require = g_ptr_array_index (requires, i);
+ if (!gs_appstream_refine_app_relation (plugin, app, require, AS_RELATION_KIND_REQUIRES,
error))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
gboolean
gs_appstream_refine_app (GsPlugin *plugin,
GsApp *app,
@@ -832,6 +931,16 @@ gs_appstream_refine_app (GsPlugin *plugin,
return FALSE;
}
+ /* recommends/requires
+ * FIXME: Technically this could do with a more specific refine flag,
+ * but essentially the relations are used on the details page and so
+ * are the permissions. It would be good to eliminate refine flags at
+ * some point in the future. */
+ if (refine_flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_PERMISSIONS) {
+ if (!gs_appstream_refine_app_relations (plugin, app, component, error))
+ return FALSE;
+ }
+
/* set name */
tmp = xb_node_query_text (component, "name", NULL);
if (tmp != NULL)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]