Hi Ludovic!
> +static void
> +guix_profile_changed (GFileMonitor *monitor,
> + GFile *file,
> + GFile *other_file,
> + GFileMonitorEvent event_type,
> + gpointer user_data)
> +{
> + DesktopFileDir *dir = user_data;
> +
> + desktop_file_dir_reset (dir);
> +
> + /* When ~/.guix-profile changes, emit the 'changed' signal so everyone
> + knows. */
> + g_app_info_monitor_fire ();
> +}
> +
> static void
> desktop_file_dir_changed (GFileMonitor *monitor,
> GFile *file,
> @@ -1531,6 +1548,7 @@ desktop_file_dirs_lock (void)
>
> if (desktop_file_dirs == NULL || desktop_file_dirs->len == 0)
> {
> + const gchar *home;
> const char * const *dirs;
> gint i;
>
> @@ -1555,6 +1573,27 @@ desktop_file_dirs_lock (void)
> for (i = 0; dirs[i]; i++)
> g_ptr_array_add (desktop_file_dirs, desktop_file_dir_new (dirs[i]));
>
> + home = g_get_home_dir ();
> + if (guix_profile_monitor == NULL && home != NULL)
> + {
> + DesktopFileDir *dir;
> + const gchar *profile, *data_dir;
> + profile = g_build_filename (home, ".guix-profile", NULL);
> + data_dir = g_build_filename (profile, "share", NULL);
> + dir = desktop_file_dir_new (data_dir);
> +
> + /* Monitor ~/.guix-profile and treat modifications to
> + ~/.guix-profile as if they were modifications to
> + ~/.guix-profile/share. */
> + guix_profile_monitor =
> + g_local_file_monitor_new_in_worker (profile, FALSE,
> G_FILE_MONITOR_NONE,
> + guix_profile_changed,
> + desktop_file_dir_ref (dir),
> + closure_notify_cb, NULL);
> +
> + g_ptr_array_add (desktop_file_dirs, desktop_file_dir_ref (dir));
> + }
> +
> /* The list of directories will never change after this, unless
> * g_get_user_config_dir() changes due to %G_TEST_OPTION_ISOLATE_DIRS.
> */
> desktop_file_dirs_config_dir = user_config_dir;
I think the attached patch is an improvement over the above, by also
supporting /run/current-system/share, being a bit simpler, and not
adding extra monitors.
I've reused the cool trick of passing FALSE to
g_local_file_monitor_new_in_worker to force it to use its polling mode
fallback.
>From a79645c565e56ac201e66936d9f9883ad9387b06 Mon Sep 17 00:00:00 2001
From: Maxim Cournoyer <[email protected]>
Date: Thu, 5 Nov 2020 00:24:29 -0500
Subject: [PATCH] gdesktopappinfo: Fix monitoring of a Guix profile
XDG_DATA_DIR.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fixes <https://issues.guix.gnu.org/35594>.
Treat the $HOME/.guix-profile/share and /run/current-system/share
XDG_DATA_DIRS file names specially so that the inotify-based monitors
placed by GLib monitor their parent link rather than an immutable
directory.
Co-authored by Ludovic Courtès <ļ[email protected]>.
---
gio/gdesktopappinfo.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
index f1e2fdd65..e659034d5 100644
--- a/gio/gdesktopappinfo.c
+++ b/gio/gdesktopappinfo.c
@@ -1380,7 +1380,8 @@ closure_notify_cb (gpointer data,
static void
desktop_file_dir_init (DesktopFileDir *dir)
{
- const gchar *watch_dir;
+ const gchar *watch_dir, *guix_profile_data, *system_profile_data;
+ gboolean is_directory = TRUE;
g_assert (!dir->is_setup);
@@ -1390,13 +1391,25 @@ desktop_file_dir_init (DesktopFileDir *dir)
dir->alternatively_watching = desktop_file_dir_get_alternative_dir (dir);
watch_dir = dir->alternatively_watching ? dir->alternatively_watching : dir->path;
+ /* Workaround for Guix: watch the link of a profile, not its
+ * immutable 'share' sub-directory. */
+ guix_profile_data = g_build_filename (g_get_home_dir (), ".guix-profile", "share", NULL);
+ system_profile_data = "/run/current-system/share";
+
+ if (g_str_equal (watch_dir, guix_profile_data)
+ || g_str_equal (watch_dir, system_profile_data))
+ {
+ is_directory = FALSE;
+ watch_dir = g_path_get_dirname (watch_dir);
+ }
+
/* There is a very thin race here if the watch_dir has been _removed_
* between when we checked for it and when we establish the watch.
* Removes probably don't happen in usual operation, and even if it
* does (and we catch the unlikely race), the only degradation is that
* we will fall back to polling.
*/
- dir->monitor = g_local_file_monitor_new_in_worker (watch_dir, TRUE, G_FILE_MONITOR_NONE,
+ dir->monitor = g_local_file_monitor_new_in_worker (watch_dir, is_directory, G_FILE_MONITOR_NONE,
desktop_file_dir_changed,
desktop_file_dir_ref (dir),
closure_notify_cb, NULL);
--
2.28.0
It's untested because 'guix vm' is taking more time to complete than I'm
willing to wait for in the middle of the night :-). I'll try it
tomorrow.
Thanks,
Maxim