Skip to content

Commit

Permalink
Merge pull request #118100 from max-privatevoid/fix/glib-appinfo-watch
Browse files Browse the repository at this point in the history
glib: follow profile updates when searching apps
  • Loading branch information
7c6f434c authored Oct 27, 2021
2 parents dbf16dc + 5b3f9e0 commit ce6b36c
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 0 deletions.
1 change: 1 addition & 0 deletions pkgs/development/libraries/glib/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
102 changes: 102 additions & 0 deletions pkgs/development/libraries/glib/glib-appinfo-watch.patch
Original file line number Diff line number Diff line change
@@ -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 <https://issues.guix.gnu.org/35594>).

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;

0 comments on commit ce6b36c

Please sign in to comment.