[rygel] core: Add mutually exclusive plugin support



commit c83fff7eceb6ab54d00ed9aec27de63abe7ca486
Author: Jens Georg <mail jensge org>
Date:   Sun Apr 19 18:13:38 2020 +0200

    core: Add mutually exclusive plugin support
    
    Add new, optional "Conflicts" keyword to the plugin meta-data which
    takes a list of names of other plugings that cannot be loaded together
    with this plugin.
    
    First plugin loaded wins
    
    Implements #155

 src/librygel-core/rygel-plugin-information.vala    | 21 +++++++--
 src/librygel-core/rygel-plugin-loader.vala         | 12 +++++
 src/plugins/tracker/tracker.plugin.in              |  1 +
 .../conflicts/librygel-no-conflict.so              |  0
 .../plugin-loader/conflicts/librygel-tracker.so    |  0
 .../plugin-loader/conflicts/librygel-tracker3.so   |  0
 tests/data/plugin-loader/conflicts/test.conf       | 11 +++++
 tests/meson.build                                  | 13 ++++++
 tests/plugin-loader/rygel-plugin-loader-test.vala  | 52 ++++++++++++++++++++++
 9 files changed, 107 insertions(+), 3 deletions(-)
---
diff --git a/src/librygel-core/rygel-plugin-information.vala b/src/librygel-core/rygel-plugin-information.vala
index 8a52a45a..845a81d5 100644
--- a/src/librygel-core/rygel-plugin-information.vala
+++ b/src/librygel-core/rygel-plugin-information.vala
@@ -41,8 +41,13 @@ public class Rygel.PluginInformation : Object {
     /// Name of this module
     public string name { get; construct; }
 
-    private PluginInformation (string module_path, string name) {
-        Object (module_path: module_path, name : name);
+    /// Name of other plugins this plugin conflicts with
+    public GenericSet<string> conflicts { get; construct; }
+
+    private PluginInformation (string module_path,
+                               string name,
+                               GenericSet<string> conflicts) {
+        Object (module_path: module_path, name : name, conflicts : conflicts);
     }
 
     /**
@@ -72,6 +77,16 @@ public class Rygel.PluginInformation : Object {
                                        module_file.get_path ());
         }
 
-        return new PluginInformation (module_file.get_path (), name);
+        var conflicts = new GenericSet<string>(str_hash, str_equal);
+        try {
+            foreach (var other_name in keyfile.get_string_list ("Plugin", "Conflicts")) {
+                other_name.strip();
+                conflicts.add (other_name);
+            }
+        } catch (KeyFileError err) {
+            // Do nothing
+        }
+
+        return new PluginInformation (module_file.get_path (), name, conflicts);
     }
 }
diff --git a/src/librygel-core/rygel-plugin-loader.vala b/src/librygel-core/rygel-plugin-loader.vala
index 736a0443..78dc8189 100644
--- a/src/librygel-core/rygel-plugin-loader.vala
+++ b/src/librygel-core/rygel-plugin-loader.vala
@@ -148,6 +148,18 @@ public class Rygel.PluginLoader : RecursiveModuleLoader {
     }
 
     protected override bool load_module_from_info (PluginInformation info) {
+        debug ("Trying to load plugin '%s'", info.name);
+
+        foreach (var conflicting in info.conflicts.get_values ()) {
+            if (this.available_plugins.has_key (conflicting)) {
+                message (_("Module '%s' conflicts with already loaded module '%s'. Skipping"),
+                         info.name,
+                         conflicting);
+
+                return false;
+            }
+        }
+
         this.available_plugins.set (info.name, info);
         if (this.plugin_disabled (info.name)) {
             debug ("Module '%s' disabled by user. Ignoring…",
diff --git a/src/plugins/tracker/tracker.plugin.in b/src/plugins/tracker/tracker.plugin.in
index 51a50a1b..ccc57997 100644
--- a/src/plugins/tracker/tracker.plugin.in
+++ b/src/plugins/tracker/tracker.plugin.in
@@ -3,5 +3,6 @@ Version = @VERSION@
 Module = tracker
 Name = Tracker
 License = LGPL
+Conflicts = Tracker3
 Description = Share media using the Tracker meta-data store
 Copyright = Copyright © Rygel maintainers
diff --git a/tests/data/plugin-loader/conflicts/librygel-no-conflict.so 
b/tests/data/plugin-loader/conflicts/librygel-no-conflict.so
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/data/plugin-loader/conflicts/librygel-tracker.so 
b/tests/data/plugin-loader/conflicts/librygel-tracker.so
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/data/plugin-loader/conflicts/librygel-tracker3.so 
b/tests/data/plugin-loader/conflicts/librygel-tracker3.so
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/data/plugin-loader/conflicts/test.conf b/tests/data/plugin-loader/conflicts/test.conf
new file mode 100644
index 00000000..85c6c8a4
--- /dev/null
+++ b/tests/data/plugin-loader/conflicts/test.conf
@@ -0,0 +1,11 @@
+[general]
+log-level = *:5
+
+[Tracker3]
+enabled = true
+
+[SomePlugin]
+enabled = true
+
+[Tracker]
+enabled = true
diff --git a/tests/meson.build b/tests/meson.build
index 9cc00e38..bb690457 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -66,6 +66,19 @@ http_time_seek_test = executable(
     dependencies : [glib, soup]
 )
 
+test('rygel-plugin-loader-test',
+    executable(
+        'rygel-plugin-loader-test',
+        files(
+            'plugin-loader/rygel-plugin-loader-test.vala'
+        ),
+        dependencies : [
+            rygel_core
+        ]
+    ),
+    workdir : meson.current_source_dir(),
+)
+
 test('rygel-searchable-container-test', searchable_container_test)
 test('rygel-object-creator-test', object_creator_test)
 test('rygel-regression-test', regression_test)
diff --git a/tests/plugin-loader/rygel-plugin-loader-test.vala 
b/tests/plugin-loader/rygel-plugin-loader-test.vala
new file mode 100644
index 00000000..3f8db60d
--- /dev/null
+++ b/tests/plugin-loader/rygel-plugin-loader-test.vala
@@ -0,0 +1,52 @@
+class TestPluginLoader : Rygel.PluginLoader {
+    private string[] expected_plugins;
+    private string[] forbidden_plugins;
+    public string[] loaded_plugins;
+
+    public TestPluginLoader(string testset_location,
+                            string[] expected_plugins,
+                            string[] forbidden_plugins) {
+        Object(base_path : "data/plugin-loader/" + testset_location);
+        this.forbidden_plugins = forbidden_plugins;
+        this.expected_plugins = expected_plugins;
+        this.loaded_plugins = new string[0];
+    }
+
+    protected override bool load_module_from_file (File module) {
+        assert (module.get_basename () in expected_plugins);
+        assert (!(module.get_basename () in forbidden_plugins));
+
+        loaded_plugins += module.get_basename ();
+
+        // Just do nothing
+        return true;
+    }
+}
+
+void test_plugin_loader_conflict () {
+    try {
+        var config = new Rygel.UserConfig.with_paths (
+            "data/plugin-loader/conflicts/test.conf",
+            "data/plugin-loader/conflicts/test.conf");
+        Rygel.MetaConfig.register_configuration (config);
+    } catch (Error error) {
+        critical("%s", error.message);
+        assert_not_reached ();
+    }
+
+    var loader = new TestPluginLoader("conflicts",
+                                      {"librygel-tracker.so", "librygel-no-conflict.so"},
+                                      {"librygel-tracker3.so"});
+    loader.load_modules_sync (null);
+    assert (loader.loaded_plugins.length == 2);
+    assert ("librygel-tracker.so" in loader.loaded_plugins);
+    assert ("librygel-no-conflict.so" in loader.loaded_plugins);
+}
+
+int main (string[] args) {
+    Test.init (ref args);
+
+    Test.add_func ("/librygel-core/plugins/load-conflict",
+                   test_plugin_loader_conflict);
+    return Test.run ();
+}
\ No newline at end of file


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]