diff --git a/pkgs/development/libraries/glib/default.nix b/pkgs/development/libraries/glib/default.nix index 4825dd98976c8..4883683215785 100644 --- a/pkgs/development/libraries/glib/default.nix +++ b/pkgs/development/libraries/glib/default.nix @@ -59,6 +59,7 @@ stdenv.mkDerivation rec { ./quark_init_on_demand.patch ./gobject_init_on_demand.patch ] ++ [ + ./glib-appinfo-watch.patch ./schema-override-variable.patch # GLib contains many binaries used for different purposes; diff --git a/pkgs/development/libraries/glib/glib-appinfo-watch.patch b/pkgs/development/libraries/glib/glib-appinfo-watch.patch new file mode 100644 index 0000000000000..cbd78a6db4a6f --- /dev/null +++ b/pkgs/development/libraries/glib/glib-appinfo-watch.patch @@ -0,0 +1,102 @@ +This patch lets GLib's GDesktopAppInfo API watch and notice changes +to the Nix user and system profiles. That way, the list of available +applications shown by the desktop environment is immediately updated +when the user installs or removes any +(see ). + +It does so by monitoring /nix/var/nix/profiles (for changes to the system +profile) and /nix/var/nix/profiles/per-user/USER (for changes to the user +profile) as well as /etc/profiles/per-user (for chanes to the user +environment profile) and crawling their share/applications sub-directory when +changes happen. + +diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c +index b779b30..31069f7 100644 +--- a/gio/gdesktopappinfo.c ++++ b/gio/gdesktopappinfo.c +@@ -150,6 +150,7 @@ typedef struct + gchar *alternatively_watching; + gboolean is_config; + gboolean is_setup; ++ gchar *nix_profile_watch_dir; + GFileMonitor *monitor; + GHashTable *app_names; + GHashTable *mime_tweaks; +@@ -181,6 +182,7 @@ desktop_file_dir_unref (DesktopFileDir *dir) + { + desktop_file_dir_reset (dir); + g_free (dir->path); ++ g_free (dir->nix_profile_watch_dir); + g_free (dir); + } + } +@@ -205,6 +207,14 @@ desktop_file_dir_get_alternative_dir (DesktopFileDir *dir) + { + gchar *parent; + ++ /* If DIR is a profile, watch the specified directory--e.g., ++ * /nix/var/nix/profiles/per-user/$USER/ for the user profile. Do not watch ++ * ~/.nix-profile or /run/current-system/sw because GFileMonitor does ++ * not pass IN_DONT_FOLLOW and thus cannot notice any change. ++ * /etc/profiles/per-user is monitored directly for the same reason. */ ++ if (dir->nix_profile_watch_dir != NULL) ++ return g_strdup (dir->nix_profile_watch_dir); ++ + /* If the directory itself exists then we need no alternative. */ + if (g_access (dir->path, R_OK | X_OK) == 0) + return NULL; +@@ -250,11 +260,11 @@ desktop_file_dir_changed (GFileMonitor *monitor, + * + * If this is a notification for a parent directory (because the + * desktop directory didn't exist) then we shouldn't fire the signal +- * unless something actually changed. ++ * unless something actually changed or it's part of a Nix profile. + */ + g_mutex_lock (&desktop_file_dir_lock); + +- if (dir->alternatively_watching) ++ if (dir->alternatively_watching && dir->nix_profile_watch_dir == NULL) + { + gchar *alternative_dir; + +@@ -1556,6 +1566,40 @@ desktop_file_dirs_lock (void) + for (i = 0; dirs[i]; i++) + g_ptr_array_add (desktop_file_dirs, desktop_file_dir_new (dirs[i])); + ++ { ++ /* Monitor the system and user profile under /nix/var/nix/profiles and ++ * treat modifications to them as if they were modifications to their ++ * /share sub-directory. */ ++ const gchar *user; ++ DesktopFileDir *system_profile_dir, *user_profile_dir, *user_env_dir; ++ ++ system_profile_dir = ++ desktop_file_dir_new ("/nix/var/nix/profiles/system/sw/share"); ++ system_profile_dir->nix_profile_watch_dir = g_strdup ("/nix/var/nix/profiles"); ++ g_ptr_array_add (desktop_file_dirs, desktop_file_dir_ref (system_profile_dir)); ++ ++ user = g_get_user_name (); ++ if (user != NULL) ++ { ++ gchar *profile_dir, *user_data_dir, *env_dir, *env_data_dir; ++ ++ profile_dir = g_build_filename ("/nix/var/nix/profiles/per-user", user, NULL); ++ user_data_dir = g_build_filename (profile_dir, "profile", "share", NULL); ++ user_profile_dir = desktop_file_dir_new (user_data_dir); ++ user_profile_dir->nix_profile_watch_dir = profile_dir; ++ ++ env_dir = g_build_filename ("/etc/profiles/per-user", NULL); ++ env_data_dir = g_build_filename (env_dir, user, "share", NULL); ++ user_env_dir = desktop_file_dir_new (env_data_dir); ++ user_env_dir->nix_profile_watch_dir = env_dir; ++ ++ g_ptr_array_add (desktop_file_dirs, desktop_file_dir_ref (user_profile_dir)); ++ g_ptr_array_add (desktop_file_dirs, desktop_file_dir_ref (user_env_dir)); ++ g_free (user_data_dir); ++ g_free (env_data_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;