Subject: [bug#54525] [patch v2 5/5] gnu: thunar: Add search path for "THUNARX_DIRS".

From: [email-masked]
Date: Tue, 29 Mar 2022 21:04:02 +0800

From: Feng Shu <[email-masked]>

* gnu/packages/xfce.scm (thunar)[native-search-paths]: new field.
[source]: Add thunar-search-paths.patch.
* gnu/local.mk: Add thunar-search-paths.patch.
---
 gnu/local.mk                                  |   1 +
 .../patches/thunar-search-paths.patch         | 214 ++++++++++++++++++
 gnu/packages/xfce.scm                         |  12 +-
 3 files changed, 226 insertions(+), 1 deletion(-)
 create mode 100644 gnu/packages/patches/thunar-search-paths.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index a704161abc..f715ec564a 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1845,6 +1845,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/texi2html-document-encoding.patch	\
   %D%/packages/patches/texi2html-i18n.patch			\
   %D%/packages/patches/thefuck-test-environ.patch		\
+  %D%/packages/patches/thunar-search-paths.patch		\
   %D%/packages/patches/tidy-CVE-2015-5522+5523.patch		\
   %D%/packages/patches/tinyxml-use-stl.patch			\
   %D%/packages/patches/tipp10-disable-downloader.patch		\
diff --git a/gnu/packages/patches/thunar-search-paths.patch b/gnu/packages/patches/thunar-search-paths.patch
new file mode 100644
index 0000000000..31f54cbdc0
--- /dev/null
+++ b/gnu/packages/patches/thunar-search-paths.patch
@@ -0,0 +1,214 @@
+From 848f1dfb2d2f404efa5371817285236d33b32a5c Mon Sep 17 00:00:00 2001
+From: tumashu <[email-masked]>
+Date: Tue, 22 Mar 2022 20:16:19 +0000
+Subject: [PATCH] Look for thunar plugins at $THUNARX_DIRS (Issue #748)
+
+THUNARX_DIRS is a list of directories where thunar plugins are looked for. It
+is needed for distributions like NixOS or Guix System that do not install all
+plugins in the same directory. In NixOS or Guix System each package is
+installed in a self contained directory.
+
+This patch has been merged into thunar master:
+1. Issue:         https://gitlab.xfce.org/xfce/thunar/-/issues/748
+2. Merge Request: https://gitlab.xfce.org/xfce/thunar/-/merge_requests/197
+
+---
+ thunarx/thunarx-provider-factory.c | 86 +++++++++++++++++-------------
+ thunarx/thunarx-provider-module.c  | 68 ++++++++++++++---------
+ 2 files changed, 91 insertions(+), 63 deletions(-)
+
+diff --git a/thunarx/thunarx-provider-factory.c b/thunarx/thunarx-provider-factory.c
+index 94b11545..386c3417 100644
+--- a/thunarx/thunarx-provider-factory.c
++++ b/thunarx/thunarx-provider-factory.c
+@@ -154,54 +154,66 @@ thunarx_provider_factory_load_modules (ThunarxProviderFactory *factory)
+   GList                 *modules = NULL;
+   GList                 *lp;
+   GDir                  *dp;
++  gchar                 *dirs_string;
++  gchar                **dirs;
+ 
+-  dp = g_dir_open (THUNARX_DIRECTORY, 0, NULL);
+-  if (G_LIKELY (dp != NULL))
++  dirs_string = (gchar *) g_getenv ("THUNARX_DIRS");
++  if (!dirs_string)
++    dirs_string = THUNARX_DIRECTORY;
++  dirs = g_strsplit (dirs_string, G_SEARCHPATH_SEPARATOR_S, 0);
++
++  for (int i = 0; dirs[i] != NULL; i++)
+     {
+-      /* determine the types for all existing plugins */
+-      for (;;)
+-        {
+-          /* read the next entry from the directory */
+-          name = g_dir_read_name (dp);
+-          if (G_UNLIKELY (name == NULL))
+-            break;
+ 
+-          /* check if this is a valid plugin file */
+-          if (g_str_has_suffix (name, "." G_MODULE_SUFFIX))
+-            {
+-              /* check if we already have that module */
+-              for (lp = thunarx_provider_modules; lp != NULL; lp = lp->next)
+-                if (g_str_equal (G_TYPE_MODULE (lp->data)->name, name))
+-                  break;
++      dp = g_dir_open (dirs[i], 0, NULL);
+ 
+-              /* use or allocate a new module for the file */
+-              if (G_UNLIKELY (lp != NULL))
+-                {
+-                  /* just use the existing module */
+-                  module = THUNARX_PROVIDER_MODULE (lp->data);
+-                }
+-              else
+-                {
+-                  /* allocate the new module and add it to our list */
+-                  module = thunarx_provider_module_new (name);
+-                  thunarx_provider_modules = g_list_prepend (thunarx_provider_modules, module);
+-                }
++      if (G_LIKELY (dp != NULL))
++        {
++          /* determine the types for all existing plugins */
++          for (;;)
++            {
++              /* read the next entry from the directory */
++              name = g_dir_read_name (dp);
++              if (G_UNLIKELY (name == NULL))
++                break;
+ 
+-              /* try to load the module */
+-              if (g_type_module_use (G_TYPE_MODULE (module)))
++              /* check if this is a valid plugin file */
++              if (g_str_has_suffix (name, "." G_MODULE_SUFFIX))
+                 {
+-                  /* add the types provided by the module */
+-                  thunarx_provider_factory_add (factory, module);
+-
+-                  /* add the module to our list */
+-                  modules = g_list_prepend (modules, module);
++                  /* check if we already have that module */
++                  for (lp = thunarx_provider_modules; lp != NULL; lp = lp->next)
++                    if (g_str_equal (G_TYPE_MODULE (lp->data)->name, name))
++                      break;
++
++                  /* use or allocate a new module for the file */
++                  if (G_UNLIKELY (lp != NULL))
++                    {
++                      continue;
++                    }
++                  else
++                    {
++                      /* allocate the new module and add it to our list */
++                      module = thunarx_provider_module_new (name);
++                      thunarx_provider_modules = g_list_prepend (thunarx_provider_modules, module);
++                    }
++
++                  /* try to load the module */
++                  if (g_type_module_use (G_TYPE_MODULE (module)))
++                    {
++                      /* add the types provided by the module */
++                      thunarx_provider_factory_add (factory, module);
++
++                      /* add the module to our list */
++                      modules = g_list_prepend (modules, module);
++                    }
+                 }
+             }
+-        }
+ 
+-      g_dir_close (dp);
++          g_dir_close (dp);
++        }
+     }
+ 
++  g_strfreev (dirs);
+   return modules;
+ }
+ 
+diff --git a/thunarx/thunarx-provider-module.c b/thunarx/thunarx-provider-module.c
+index 023ad2ae..5ddf38b2 100644
+--- a/thunarx/thunarx-provider-module.c
++++ b/thunarx/thunarx-provider-module.c
+@@ -175,37 +175,53 @@ thunarx_provider_module_load (GTypeModule *type_module)
+ {
+   ThunarxProviderModule *module = THUNARX_PROVIDER_MODULE (type_module);
+   gchar                 *path;
++  gchar                 *dirs_string;
++  gchar                **dirs;
++  gboolean               found;
+ 
+-  /* load the module using the runtime link editor */
+-  path = g_build_filename (THUNARX_DIRECTORY, type_module->name, NULL);
+-  module->library = g_module_open (path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+-  g_free (path);
++  dirs_string = (gchar *) g_getenv ("THUNARX_DIRS");
++  if (!dirs_string)
++    dirs_string = THUNARX_DIRECTORY;
++  dirs = g_strsplit (dirs_string, G_SEARCHPATH_SEPARATOR_S, 0);
+ 
+-  /* check if the load operation was successfull */
+-  if (G_UNLIKELY (module->library == NULL))
+-    {
+-      g_printerr ("Thunar :Failed to load plugin `%s': %s\n", type_module->name, g_module_error ());
+-      return FALSE;
+-    }
++  found = FALSE;
+ 
+-  /* verify that all required public symbols are present in the plugin's symbol table */
+-  if (!g_module_symbol (module->library, "thunar_extension_shutdown", (gpointer) &module->shutdown)
+-      || !g_module_symbol (module->library, "thunar_extension_initialize", (gpointer) &module->initialize)
+-      || !g_module_symbol (module->library, "thunar_extension_list_types", (gpointer) &module->list_types))
++  for (int i = 0; !found && dirs[i] != NULL; i++)
+     {
+-      g_printerr ("Thunar :Plugin `%s' lacks required symbols.\n", type_module->name);
+-      g_module_close (module->library);
+-      return FALSE;
++      /* load the module using the runtime link editor */
++      path = g_build_filename (dirs[i], type_module->name, NULL);
++
++      module->library = g_module_open (path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
++      g_free (path);
++
++      /* check if the load operation was successfull */
++      if (G_UNLIKELY (module->library == NULL))
++        {
++          g_printerr ("Thunar :Failed to load plugin `%s' from `%s': %s\n", type_module->name, path, g_module_error ());
++          continue;
++        }
++
++      /* verify that all required public symbols are present in the plugin's symbol table */
++      if (!g_module_symbol (module->library, "thunar_extension_shutdown", (gpointer) &module->shutdown)
++          || !g_module_symbol (module->library, "thunar_extension_initialize", (gpointer) &module->initialize)
++          || !g_module_symbol (module->library, "thunar_extension_list_types", (gpointer) &module->list_types))
++        {
++          g_printerr ("Thunar :Plugin `%s' in `%s' lacks required symbols.\n", type_module->name, path);
++          g_module_close (module->library);
++          continue;
++        }
++
++      /* initialize the plugin */
++      (*module->initialize) (module);
++
++      /* ensure that the module will never be unloaded if it requests to be kept in memory */
++      if (G_UNLIKELY (module->resident))
++        g_module_make_resident (module->library);
++
++      found = TRUE;
+     }
+-
+-  /* initialize the plugin */
+-  (*module->initialize) (module);
+-
+-  /* ensure that the module will never be unloaded if it requests to be kept in memory */
+-  if (G_UNLIKELY (module->resident))
+-    g_module_make_resident (module->library);
+-
+-  return TRUE;
++  g_strfreev (dirs);
++  return found;
+ }
+ 
+ 
+-- 
+2.34.0
+
diff --git a/gnu/packages/xfce.scm b/gnu/packages/xfce.scm
index 182fe0fd8f..d3b3026d14 100644
--- a/gnu/packages/xfce.scm
+++ b/gnu/packages/xfce.scm
@@ -16,6 +16,7 @@
 ;;; Copyright © 2020, 2021, 2022 Michael Rohleder <[email-masked]>
 ;;; Copyright © 2021 Brendan Tildesley <[email-masked]>
 ;;; Copyright © 2021 André A. Gomes <[email-masked]>
+;;; Copyright © 2022 Feng Shu <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -747,7 +748,12 @@ (define-public thunar
                                   "thunar-" version ".tar.bz2"))
               (sha256
                (base32
-                "14lwi4ax0wj77980kkfhdf18b97339b17y8qc8gl2365mgswh1gi"))))
+                "14lwi4ax0wj77980kkfhdf18b97339b17y8qc8gl2365mgswh1gi"))
+              (patches
+               (search-patches
+                ;; NOTE: This patch is backported from thunar.git, it should
+                ;; be removed when update to thunar-4.18.
+                "thunar-search-paths.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      (list pkg-config intltool))
@@ -762,6 +768,10 @@ (define-public thunar
            pcre
            xfce4-panel
            startup-notification))
+    (native-search-paths
+     (list (search-path-specification
+            (variable "THUNARX_DIRS")
+            (files (list "lib/thunarx-3")))))
     (home-page "https://www.xfce.org/")
     (synopsis "Xfce file manager")
     (description
-- 
2.34.0