--- a/gplugin/gplugin-manager.c Sun Feb 23 00:16:56 2020 -0600
+++ b/gplugin/gplugin-manager.c Sun Feb 23 03:58:53 2020 -0600
@@ -61,6 +61,7 @@
GHashTable *plugins_filename_view;
GHashTable *loaders_by_extension;
@@ -76,8 +77,8 @@
GList *(*get_paths)(GPluginManager *manager);
- void (*register_loader)(GPluginManager *manager, GType type);
- void (*unregister_loader)(GPluginManager *manager, GType type);
+ gboolean (*register_loader)(GPluginManager *manager, GType type, GError **error); + gboolean (*unregister_loader)(GPluginManager *manager, GType type, GError **error); void (*refresh)(GPluginManager *manager);
@@ -156,6 +157,31 @@
+ * gplugin_manager_find_loader_by_type: + * @manager: The #GPluginManager instance. + * @type: The #GType of the loader to find. + * Looks up a #GPluginLoader instance by it's type. + * Returns: (transfer none): The #GPluginLoader instance or %NULL. +gplugin_manager_find_loader_by_type(GPluginManager *manager, GType type) { + g_return_val_if_fail(GPLUGIN_IS_MANAGER(manager), NULL); + g_return_val_if_fail(g_type_is_a(type, GPLUGIN_TYPE_LOADER), NULL); + for(l = manager->loaders; l; l = l->next) { + if(G_OBJECT_TYPE(l->data) == type) { + return GPLUGIN_LOADER(l->data); /******************************************************************************
*****************************************************************************/
@@ -219,37 +245,49 @@
return manager->paths->head;
-gplugin_manager_real_register_loader(GPluginManager *manager,
+gplugin_manager_real_register_loader(GPluginManager *manager, GType type, GPluginLoader *loader = NULL;
GPluginLoaderClass *lo_class = NULL;
+ GSList *l = NULL, *exts = NULL; + g_return_val_if_fail(g_type_is_a(type, GPLUGIN_TYPE_LOADER), FALSE); - g_return_if_fail(g_type_is_a(type, GPLUGIN_TYPE_LOADER));
+ loader = gplugin_manager_find_loader_by_type(manager, type); + if(GPLUGIN_IS_LOADER(loader)) { + g_set_error(error, GPLUGIN_DOMAIN, 0, + _("loader %s was already registered"), g_type_name(type)); /* Create the loader instance first. If we can't create it, we bail */
loader = g_object_new(type, NULL);
if(!GPLUGIN_IS_LOADER(loader)) {
- g_warning(_("failed to create loader instance for %s"),
+ g_set_error(error, GPLUGIN_DOMAIN, 0, + _("failed to create loader instance for %s"),
/* grab the class of the loader */
lo_class = GPLUGIN_LOADER_GET_CLASS(loader);
- g_warning(_("failed to get the loader class for %s"), g_type_name(type));
+ g_set_error(error, GPLUGIN_DOMAIN, 0, + _("failed to get the loader class for %s"), g_object_unref(G_OBJECT(loader));
- for(l = gplugin_loader_class_get_supported_extensions(lo_class);
+ manager->loaders = g_slist_prepend(manager->loaders, + g_object_ref(G_OBJECT(loader))); + exts = gplugin_loader_class_get_supported_extensions(lo_class); + for(l = exts; l; l = l->next) { GSList *existing = NULL, *ll = NULL;
const gchar *ext = (const gchar *)l->data;
@@ -276,26 +314,42 @@
g_hash_table_insert(manager->loaders_by_extension, g_strdup(ext),
/* make a note that we need to refresh */
manager->refresh_needed = TRUE;
/* we remove our initial reference from the loader now to avoid a leak */
g_object_unref(G_OBJECT(loader));
-gplugin_manager_real_unregister_loader(GPluginManager *manager,
+gplugin_manager_real_unregister_loader(GPluginManager *manager, GType type, + GPluginLoader *loader = NULL; GPluginLoaderClass *klass = NULL;
- g_return_if_fail(g_type_is_a(type, GPLUGIN_TYPE_LOADER));
+ g_return_val_if_fail(g_type_is_a(type, GPLUGIN_TYPE_LOADER), FALSE); + loader = gplugin_manager_find_loader_by_type(manager, type); + if(!GPLUGIN_IS_LOADER(loader)) { + g_set_error(error, GPLUGIN_DOMAIN, 0, + _("loader %s is not registered"), g_type_name(type)); - klass = g_type_class_ref(type);
+ klass = GPLUGIN_LOADER_GET_CLASS(loader); + g_set_error_literal(error, GPLUGIN_DOMAIN, 0, + _("failed to get class from loader")); for(exts = gplugin_loader_class_get_supported_extensions(klass);
exts; exts = exts->next) {
@@ -326,15 +380,15 @@
g_hash_table_remove(manager->loaders_by_extension, ext);
- /* kill our ref to the loader */
- g_object_unref(G_OBJECT(lo));
/* now move to the next extension to check */
- g_type_class_unref(klass);
+ manager->loaders = g_slist_remove(manager->loaders, loader); + g_object_unref(G_OBJECT(loader)); @@ -852,6 +906,10 @@
/* destroy the filename view */
g_clear_pointer(&manager->plugins_filename_view, g_hash_table_destroy);
+ /* clean up our list of loaders */ + g_slist_free_full(manager->loaders, g_object_unref); + manager->loaders = NULL; /* free all the data in the loaders hash table and destroy it */
g_hash_table_foreach_remove(manager->loaders_by_extension,
gplugin_manager_remove_list_value,
@@ -1034,13 +1092,17 @@
*****************************************************************************/
gplugin_manager_private_init(void) {
instance = g_object_new(GPLUGIN_TYPE_MANAGER, NULL);
- gplugin_manager_register_loader(GPLUGIN_TYPE_NATIVE_LOADER);
+ if(!gplugin_manager_register_loader(GPLUGIN_TYPE_NATIVE_LOADER, &error)) { + g_error("failed to register loader %s", error->message); dependency_regex = g_regex_new(dependency_pattern, 0, 0, NULL);
@@ -1203,37 +1265,49 @@
* gplugin_manager_register_loader:
* @type: #GType of a #GPluginLoader.
+ * @error: (out) (nullable): The return address for a #GError. * Registers @type as an available loader.
+ * Returns: %TRUE if the loader was successfully register, %FALSE otherwise
-gplugin_manager_register_loader(GType type) {
+gplugin_manager_register_loader(GType type, GError **error) { GPluginManager *manager = GPLUGIN_MANAGER_INSTANCE;
GPluginManagerClass *klass = NULL;
- g_return_if_fail(GPLUGIN_IS_MANAGER(manager));
+ g_return_val_if_fail(GPLUGIN_IS_MANAGER(manager), FALSE); klass = GPLUGIN_MANAGER_GET_CLASS(manager);
if(klass && klass->register_loader)
- klass->register_loader(manager, type);
+ return klass->register_loader(manager, type, error); * gplugin_manager_unregister_loader:
* @type: #GType of a #GPluginLoader.
+ * @error: (out) (nullable): The return address for a #GError. * Unregisters @type as an available loader.
+ * Returns: %TRUE if the loader was successfully unregistered, %FALSE + * otherwise with @error set.
-gplugin_manager_unregister_loader(GType type) {
+gplugin_manager_unregister_loader(GType type, GError **error) { GPluginManager *manager = GPLUGIN_MANAGER_INSTANCE;
GPluginManagerClass *klass = NULL;
- g_return_if_fail(GPLUGIN_IS_MANAGER(manager));
+ g_return_val_if_fail(GPLUGIN_IS_MANAGER(manager), FALSE); klass = GPLUGIN_MANAGER_GET_CLASS(manager);
if(klass && klass->unregister_loader)
- klass->unregister_loader(manager, type);
+ return klass->unregister_loader(manager, type, error); --- a/gplugin/tests/meson.build Sun Feb 23 00:16:56 2020 -0600
+++ b/gplugin/tests/meson.build Sun Feb 23 03:58:53 2020 -0600
@@ -28,6 +28,10 @@
dependencies : [gplugin_dep, GLIB, GOBJECT])
+e = executable('test-loader-registration', 'test-loader-registration.c', + dependencies : [gplugin_dep, GLIB, GOBJECT]) +test('Loader Registration', e) e = executable('test-option-group', 'test-option-group.c',
dependencies : [gplugin_dep, GLIB, GOBJECT])