gplugin/gplugin

Parents 57fad55b7388
Children 2b8af6f9b838
Add GPluginPluginInfo:provides and GPluginPluginInfo:priority properties

This is just the properties and none of the behavior yet. I'm doing this in two phases to make it easier to reason about as `gplugin_manager_refresh` is going to need some refactoring to make this all work.

Testing Done:
Ran the unit tests.

Bugs closed: GPLUGIN-79

Reviewed at https://reviews.imfreedom.org/r/691/
--- a/gplugin/gplugin-plugin-info.c Wed Jun 02 03:01:51 2021 -0500
+++ b/gplugin/gplugin-plugin-info.c Mon Jun 14 03:58:40 2021 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2020 Gary Kramlich <grim@reaperworld.com>
+ * Copyright (C) 2011-2021 Gary Kramlich <grim@reaperworld.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -53,6 +53,9 @@
typedef struct {
gchar *id;
+ gchar **provides;
+ gint priority;
+
gchar *name;
gchar *version;
@@ -84,6 +87,8 @@
enum {
PROP_ZERO = 0,
PROP_ID,
+ PROP_PROVIDES,
+ PROP_PRIORITY,
PROP_ABI_VERSION,
PROP_INTERNAL,
PROP_LOQ,
@@ -125,6 +130,32 @@
}
static void
+gplugin_plugin_info_set_provides(
+ GPluginPluginInfo *info,
+ const gchar *const *provides)
+{
+ GPluginPluginInfoPrivate *priv =
+ gplugin_plugin_info_get_instance_private(info);
+
+ g_strfreev(priv->provides);
+
+ priv->provides = g_strdupv((gchar **)provides);
+
+ g_object_notify_by_pspec(G_OBJECT(info), properties[PROP_PROVIDES]);
+}
+
+static void
+gplugin_plugin_info_set_priority(GPluginPluginInfo *info, gint priority) {
+ GPluginPluginInfoPrivate *priv = gplugin_plugin_info_get_instance_private(info);
+
+ if(priority != priv->priority) {
+ priv->priority = priority;
+
+ g_object_notify_by_pspec(G_OBJECT(info), properties[PROP_PRIORITY]);
+ }
+}
+
+static void
gplugin_plugin_info_set_abi_version(
GPluginPluginInfo *info,
guint32 abi_version)
@@ -316,6 +347,12 @@
case PROP_ID:
g_value_set_string(value, gplugin_plugin_info_get_id(info));
break;
+ case PROP_PROVIDES:
+ g_value_set_boxed(value, gplugin_plugin_info_get_provides(info));
+ break;
+ case PROP_PRIORITY:
+ g_value_set_int(value, gplugin_plugin_info_get_priority(info));
+ break;
case PROP_ABI_VERSION:
g_value_set_uint(value, gplugin_plugin_info_get_abi_version(info));
break;
@@ -395,6 +432,12 @@
case PROP_ID:
gplugin_plugin_info_set_id(info, g_value_get_string(value));
break;
+ case PROP_PROVIDES:
+ gplugin_plugin_info_set_provides(info, g_value_get_boxed(value));
+ break;
+ case PROP_PRIORITY:
+ gplugin_plugin_info_set_priority(info, g_value_get_int(value));
+ break;
case PROP_ABI_VERSION:
gplugin_plugin_info_set_abi_version(info, g_value_get_uint(value));
break;
@@ -468,6 +511,7 @@
gplugin_plugin_info_get_instance_private(GPLUGIN_PLUGIN_INFO(obj));
g_clear_pointer(&priv->id, g_free);
+ g_clear_pointer(&priv->provides, g_strfreev);
g_clear_pointer(&priv->name, g_free);
g_clear_pointer(&priv->version, g_free);
g_clear_pointer(&priv->license_id, g_free);
@@ -518,6 +562,41 @@
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
/**
+ * GPluginPluginInfo:provides:
+ *
+ * A list of additional plugin ids and versions that this plugin can
+ * provide. This mechanism is used so that plugins can replace and extend
+ * the behavior of other plugins.
+ *
+ * The format fields should either be <literal>&lt;plugin-id&gt;</literal>
+ * or <literal>&lt;plugin-id&gt;=&lt;plugin-version&gt;</literal>. The
+ * optional version is used to help resolve dependencies that are based
+ * on a specific version.
+ *
+ * Since: 0.32.0
+ */
+ properties[PROP_PROVIDES] = g_param_spec_boxed(
+ "provides",
+ "provides",
+ "The additional ids that this plugin provides.",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
+
+ /**
+ * GPluginPluginInfo:priority:
+ *
+ * The priority that this plugin should have when determining which plugin
+ * to use when multiple plugins have the same id or provides. Higher values
+ * take precedence over lower values. If two plugins have the same id and
+ * priority, the first one found will be used.
+ *
+ * Since: 0.32.0
+ */
+ properties[PROP_PRIORITY] = g_param_spec_int(
+ "priority", "priority", "The priority of the plugin", G_MININT, G_MAXINT, 0,
+G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ /**
* GPluginPluginInfo:abi-version:
*
* The GPlugin ABI version that the plugin was compiled against.
@@ -826,6 +905,50 @@
}
/**
+ * gplugin_plugin_info_get_provides:
+ * @info: The #GPluginPluginInfo instance.
+ *
+ * Gets the provides of the plugin as specified in @info.
+ *
+ * Returns: (array zero-terminated=1) (transfer none): The list of
+ * dependencies from @info.
+ *
+ * Since: 0.32.0
+ */
+const gchar *const *
+gplugin_plugin_info_get_provides(GPluginPluginInfo *info)
+{
+ GPluginPluginInfoPrivate *priv = NULL;
+
+ g_return_val_if_fail(GPLUGIN_IS_PLUGIN_INFO(info), NULL);
+
+ priv = gplugin_plugin_info_get_instance_private(info);
+
+ return (const gchar *const *)priv->provides;
+}
+
+/**
+ * gplugin_plugin_info_get_priority:
+ * @info: The #GPluginPluginInfo instance.
+ *
+ * Gets the priority of the plugin as specified in @info.
+ *
+ * Returns: The priority from @info.
+ *
+ * Since: 0.32.0
+ */
+gint
+gplugin_plugin_info_get_priority(GPluginPluginInfo *info) {
+ GPluginPluginInfoPrivate *priv = NULL;
+
+ g_return_val_if_fail(GPLUGIN_IS_PLUGIN_INFO(info), 0);
+
+ priv = gplugin_plugin_info_get_instance_private(info);
+
+ return priv->priority;
+}
+
+/**
* gplugin_plugin_info_get_abi_version:
* @info: The #GPluginPluginInfo instance.
*
--- a/gplugin/gplugin-plugin-info.h Wed Jun 02 03:01:51 2021 -0500
+++ b/gplugin/gplugin-plugin-info.h Mon Jun 14 03:58:40 2021 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2020 Gary Kramlich <grim@reaperworld.com>
+ * Copyright (C) 2011-2021 Gary Kramlich <grim@reaperworld.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -56,6 +56,8 @@
const gchar *gplugin_plugin_info_get_id(GPluginPluginInfo *info);
gchar *gplugin_info_get_id_normalized(GPluginPluginInfo *info);
+const gchar *const *gplugin_plugin_info_get_provides(GPluginPluginInfo *info);
+gint gplugin_plugin_info_get_priority(GPluginPluginInfo *info);
guint32 gplugin_plugin_info_get_abi_version(GPluginPluginInfo *info);
gboolean gplugin_plugin_info_get_internal(GPluginPluginInfo *info);
gboolean gplugin_plugin_info_get_load_on_query(GPluginPluginInfo *info);
--- a/gplugin/tests/test-plugin-info.c Wed Jun 02 03:01:51 2021 -0500
+++ b/gplugin/tests/test-plugin-info.c Mon Jun 14 03:58:40 2021 -0500
@@ -29,6 +29,14 @@
} \
G_STMT_END
+#define test_int(var, value) \
+ G_STMT_START \
+ { \
+ g_assert_cmpint((var), ==, (value)); \
+ g_assert_cmpint((var), ==, gplugin_plugin_info_get_##var(info)); \
+ } \
+ G_STMT_END
+
#define test_uint(var, value) \
G_STMT_START \
{ \
@@ -95,9 +103,11 @@
gchar *license_id = NULL, *license_text = NULL, *license_url = NULL;
gchar *summary = NULL, *description = NULL, *category = NULL;
gchar *website = NULL;
- gchar **authors = NULL, **dependencies = NULL;
+ gchar **provides = NULL, **authors = NULL, **dependencies = NULL;
+ gint priority = 0;
guint abi_version = 0;
gboolean internal = FALSE, load_on_query = FALSE;
+ const gchar *const r_provides[] = {"foo", NULL};
const gchar *const r_authors[] = {"author", NULL};
const gchar *const r_dependencies[] = {"dependency", NULL};
@@ -105,6 +115,8 @@
info = g_object_new(
GPLUGIN_TYPE_PLUGIN_INFO,
"id", "gplugin-test/plugin-info-test",
+ "provides", r_provides,
+ "priority", 1000,
"abi_version", GPLUGIN_NATIVE_PLUGIN_ABI_VERSION,
"internal", TRUE,
"load-on-query", TRUE,
@@ -129,6 +141,8 @@
g_object_get(
G_OBJECT(info),
"id", &id,
+ "provides", &provides,
+ "priority", &priority,
"abi_version", &abi_version,
"internal", &internal,
"load-on-query", &load_on_query,
@@ -148,6 +162,12 @@
/* clang-format on */
test_string(id, "gplugin-test/plugin-info-test");
+ test_stringv(
+ provides,
+ r_provides,
+ (TestStringVFunc)gplugin_plugin_info_get_provides,
+ info);
+ test_int(priority, 1000);
test_uint(abi_version, GPLUGIN_NATIVE_PLUGIN_ABI_VERSION);
test_true(internal);
test_true(load_on_query);