Hello community, here is the log from the commit of package cinnamon-menus for openSUSE:Factory checked in at 2016-05-29 03:11:47 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/cinnamon-menus (Old) and /work/SRC/openSUSE:Factory/.cinnamon-menus.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "cinnamon-menus" Changes: -------- --- /work/SRC/openSUSE:Factory/cinnamon-menus/cinnamon-menus.changes 2016-04-28 17:01:20.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.cinnamon-menus.new/cinnamon-menus.changes 2016-05-29 03:12:56.000000000 +0200 @@ -1,0 +2,12 @@ +Tue May 24 16:25:54 UTC 2016 - [email protected] + +- Update to version 3.0.1: + * entry-directories.c: Monitor mimeinfo.cache file and + re-attempt failed .desktop files when it changes (which is + usually just after the .desktop file is added, causing loading + to fail due to unavailable GAppInfo). + * desktop-entries.c: Refactor to eliminate double-loading of + .desktop file. Use g_key_file_load_from_file, followed by + g_desktop_app_info_new_from_keyfile. + +------------------------------------------------------------------- Old: ---- cinnamon-menus-3.0.0.tar.gz New: ---- cinnamon-menus-3.0.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ cinnamon-menus.spec ++++++ --- /var/tmp/diff_new_pack.Iuk1CA/_old 2016-05-29 03:12:57.000000000 +0200 +++ /var/tmp/diff_new_pack.Iuk1CA/_new 2016-05-29 03:12:57.000000000 +0200 @@ -20,7 +20,7 @@ %define soname libcinnamon-menu-3 %define sover 0 Name: cinnamon-menus -Version: 3.0.0 +Version: 3.0.1 Release: 0 Summary: A menu system for the Cinnamon Desktop License: LGPL-2.1+ ++++++ cinnamon-menus-3.0.0.tar.gz -> cinnamon-menus-3.0.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cinnamon-menus-3.0.0/configure.ac new/cinnamon-menus-3.0.1/configure.ac --- old/cinnamon-menus-3.0.0/configure.ac 2016-04-23 16:57:07.000000000 +0200 +++ new/cinnamon-menus-3.0.1/configure.ac 2016-05-23 13:55:09.000000000 +0200 @@ -1,6 +1,6 @@ AC_PREREQ(2.62) -AC_INIT([cinnamon-menus], [3.0.0]) +AC_INIT([cinnamon-menus], [3.0.1]) AC_CONFIG_SRCDIR(libmenu/gmenu-tree.h) AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cinnamon-menus-3.0.0/debian/changelog new/cinnamon-menus-3.0.1/debian/changelog --- old/cinnamon-menus-3.0.0/debian/changelog 2016-04-23 16:57:07.000000000 +0200 +++ new/cinnamon-menus-3.0.1/debian/changelog 2016-05-23 13:55:09.000000000 +0200 @@ -1,3 +1,12 @@ +cinnamon-menus (3.0.1) sarah; urgency=medium + + [ Michael Webster ] + * entry-directories.c: Monitor mimeinfo.cache file and re-attempt failed .desktop files when it changes (which is usually just after the .desktop file is added, causing loading to fail due to unavailable GAppInfo). See inline comments. + * Follow-up to previous commit - retry only those desktop files that failed because of appinfo problems. + * desktop-entries.c: Refactor to eliminate double-loading of desktop file. Use g_key_file_load_from_file, followed by g_desktop_app_info_new_from_keyfile. + + -- Clement Lefebvre <[email protected]> Mon, 23 May 2016 12:54:12 +0100 + cinnamon-menus (3.0.0) sarah; urgency=medium [ monsta ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cinnamon-menus-3.0.0/libmenu/desktop-entries.c new/cinnamon-menus-3.0.1/libmenu/desktop-entries.c --- old/cinnamon-menus-3.0.0/libmenu/desktop-entries.c 2016-04-23 16:57:07.000000000 +0200 +++ new/cinnamon-menus-3.0.1/libmenu/desktop-entries.c 2016-05-23 13:55:09.000000000 +0200 @@ -263,72 +263,89 @@ return TRUE; } -static gboolean +static DesktopEntryResultCode desktop_entry_load (DesktopEntry *entry) { + DesktopEntryResultCode rescode = DESKTOP_ENTRY_LOAD_FAIL_OTHER; + if (strstr (entry->path, "/menu-xdg/")) - return FALSE; + return rescode; + if (entry->type == DESKTOP_ENTRY_DESKTOP) { GKeyFile *key_file = NULL; DesktopEntryDesktop *entry_desktop = (DesktopEntryDesktop*)entry; - const char *categories_str; - entry_desktop->appinfo = g_desktop_app_info_new_from_filename (entry->path); - if (!entry_desktop->appinfo || - !g_app_info_get_name (G_APP_INFO (entry_desktop->appinfo)) || - !g_app_info_get_executable (G_APP_INFO (entry_desktop->appinfo))) - { - menu_verbose ("Failed to load \"%s\"\n", entry->path); - return FALSE; - } + key_file = g_key_file_new (); - categories_str = g_desktop_app_info_get_categories (entry_desktop->appinfo); - if (categories_str) + if (g_key_file_load_from_file (key_file, entry->path, 0, NULL)) { - char **categories; - int i; + entry_desktop->appinfo = g_desktop_app_info_new_from_keyfile (key_file); - categories = g_strsplit (categories_str, ";", -1); - entry_desktop->categories = g_new0 (GQuark, g_strv_length (categories) + 1); + if (!entry_desktop->appinfo || + !g_app_info_get_name (G_APP_INFO (entry_desktop->appinfo)) || + !g_app_info_get_executable (G_APP_INFO (entry_desktop->appinfo))) + { + menu_verbose ("Failed to load appinfo for \"%s\"\n", entry->path); + rescode = DESKTOP_ENTRY_LOAD_FAIL_APPINFO; + } + else + { + const char *categories_str; + categories_str = g_desktop_app_info_get_categories (entry_desktop->appinfo); - for (i = 0; categories[i]; i++) - entry_desktop->categories[i] = g_quark_from_string (categories[i]); + if (categories_str) + { + char **categories; + int i; - g_strfreev (categories); - } + categories = g_strsplit (categories_str, ";", -1); + entry_desktop->categories = g_new0 (GQuark, g_strv_length (categories) + 1); - key_file = g_key_file_new (); + for (i = 0; categories[i]; i++) + entry_desktop->categories[i] = g_quark_from_string (categories[i]); - if (!g_key_file_load_from_file (key_file, entry->path, 0, NULL)) - entry_desktop->showin = TRUE; - else - entry_desktop->showin = key_file_get_show_in (key_file); + g_strfreev (categories); + } - g_key_file_free (key_file); + entry_desktop->showin = key_file_get_show_in (key_file); - return TRUE; + rescode = DESKTOP_ENTRY_LOAD_SUCCESS; + } + } + else + { + menu_verbose ("Failed to read contents of \"%s\"\n", entry->path); + rescode = DESKTOP_ENTRY_LOAD_FAIL_OTHER; + } + g_key_file_free (key_file); } else if (entry->type == DESKTOP_ENTRY_DIRECTORY) { GKeyFile *key_file = NULL; GError *error = NULL; - gboolean retval = FALSE; + rescode = DESKTOP_ENTRY_LOAD_SUCCESS; key_file = g_key_file_new (); if (!g_key_file_load_from_file (key_file, entry->path, 0, &error)) - goto out; + { + rescode = DESKTOP_ENTRY_LOAD_FAIL_OTHER; + goto out; + } if (!desktop_entry_load_directory (entry, key_file, &error)) - goto out; + { + rescode = DESKTOP_ENTRY_LOAD_FAIL_OTHER; + goto out; + } - retval = TRUE; + rescode = DESKTOP_ENTRY_LOAD_SUCCESS; out: g_key_file_free (key_file); - if (!retval) + if (rescode == DESKTOP_ENTRY_LOAD_FAIL_OTHER) { if (error) { @@ -338,20 +355,27 @@ else menu_verbose ("Failed to load \"%s\"\n", entry->path); } - - return retval; } else g_assert_not_reached (); - return FALSE; + return rescode; +} + +static gboolean +code_failed (DesktopEntryResultCode code) +{ + return code == DESKTOP_ENTRY_LOAD_FAIL_OTHER || + code == DESKTOP_ENTRY_LOAD_FAIL_APPINFO; } DesktopEntry * -desktop_entry_new (const char *path) +desktop_entry_new (const char *path, + DesktopEntryResultCode *res_code) { DesktopEntryType type; DesktopEntry *retval; + DesktopEntryResultCode code; menu_verbose ("Loading desktop entry \"%s\"\n", path); @@ -369,6 +393,7 @@ { menu_verbose ("Unknown desktop entry suffix in \"%s\"\n", path); + *res_code = DESKTOP_ENTRY_LOAD_FAIL_OTHER; return NULL; } @@ -377,7 +402,10 @@ retval->path = g_strdup (path); retval->basename = unix_basename_from_path (retval->path); - if (!desktop_entry_load (retval)) + code = desktop_entry_load (retval); + *res_code = code; + + if (code_failed (code)) { desktop_entry_unref (retval); return NULL; @@ -419,7 +447,7 @@ else g_assert_not_reached (); - if (!desktop_entry_load (entry)) + if (code_failed (desktop_entry_load (entry))) { desktop_entry_unref (entry); return NULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cinnamon-menus-3.0.0/libmenu/desktop-entries.h new/cinnamon-menus-3.0.1/libmenu/desktop-entries.h --- old/cinnamon-menus-3.0.0/libmenu/desktop-entries.h 2016-04-23 16:57:07.000000000 +0200 +++ new/cinnamon-menus-3.0.1/libmenu/desktop-entries.h 2016-05-23 13:55:09.000000000 +0200 @@ -31,9 +31,17 @@ DESKTOP_ENTRY_DIRECTORY } DesktopEntryType; +typedef enum +{ + DESKTOP_ENTRY_LOAD_SUCCESS = 0, + DESKTOP_ENTRY_LOAD_FAIL_OTHER, + DESKTOP_ENTRY_LOAD_FAIL_APPINFO +} DesktopEntryResultCode; + typedef struct DesktopEntry DesktopEntry; -DesktopEntry *desktop_entry_new (const char *path); +DesktopEntry *desktop_entry_new (const char *path, + DesktopEntryResultCode *res_code); DesktopEntry *desktop_entry_ref (DesktopEntry *entry); DesktopEntry *desktop_entry_copy (DesktopEntry *entry); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cinnamon-menus-3.0.0/libmenu/entry-directories.c new/cinnamon-menus-3.0.1/libmenu/entry-directories.c --- old/cinnamon-menus-3.0.0/libmenu/entry-directories.c 2016-04-23 16:57:07.000000000 +0200 +++ new/cinnamon-menus-3.0.1/libmenu/entry-directories.c 2016-05-23 13:55:09.000000000 +0200 @@ -57,6 +57,7 @@ GSList *entries; GSList *subdirs; + GSList *retry_later_desktop_entries; MenuMonitor *dir_monitor; GSList *monitors; @@ -161,6 +162,9 @@ g_slist_free (dir->subdirs); dir->subdirs = NULL; + g_slist_free_full (dir->retry_later_desktop_entries, g_free); + dir->retry_later_desktop_entries = NULL; + g_free (dir->name); g_free (dir); } @@ -314,10 +318,20 @@ const char *path) { DesktopEntry *entry; + DesktopEntryResultCode code; - entry = desktop_entry_new (path); + entry = desktop_entry_new (path, &code); if (entry == NULL) - return FALSE; + { + if (code == DESKTOP_ENTRY_LOAD_FAIL_APPINFO) + { + menu_verbose ("Adding %s to the retry list (mimeinfo.cache maybe isn't done getting updated yet\n", path); + + dir->retry_later_desktop_entries = g_slist_prepend (dir->retry_later_desktop_entries, g_strdup (path)); + } + + return FALSE; + } dir->entries = g_slist_prepend (dir->entries, entry); @@ -525,6 +539,8 @@ CachedDir *dir) { gboolean handled = FALSE; + gboolean retry_changes = FALSE; + char *basename; char *dirname; @@ -558,6 +574,58 @@ break; } } + else if (g_strcmp0 (basename, "mimeinfo.cache") == 0) + { + /* The observed file notifies when a new desktop file is added + * (but fails to load) go something like: + * + * NOTIFY: foo.desktop + * NOTIFY: mimeinfo.cache.tempfile + * NOTIFY: mimeinfo.cache.tempfile + * NOTIFY: mimeinfo.cache + * + * Additionally, the failure is not upon trying to read the file, + * but attempting to get its GAppInfo (g_desktop_app_info_new_from_filename() + * in desktop-entries.c ln 277). If you jigger desktop_entry_load() around + * and read the file as a keyfile *first*, it succeeds. If you then try + * to run g_desktop_app_info_new_from_keyfile(), *then* it fails. + * + * The theory here is there is a race condition where app info (which includes + * mimetype stuff) is unavailable because mimeinfo.cache is updated immediately + * after the app is installed. + * + * What we do here is, when a desktop fails to load, we add it to a temporary + * list. We wait until mimeinfo.cache changes, then retry that desktop file, + * which succeeds this second time. + * + * Note: An alternative fix (presented more as a proof than a suggestion) is to + * change line 151 in menu-monitor.c to use g_timeout_add_seconds, and delay + * for one second. This also avoids the issue (but it remains a race condition). + */ + + GSList *iter; + + menu_verbose ("mimeinfo changed, checking for failed entries\n"); + + for (iter = dir->retry_later_desktop_entries; iter != NULL; iter = iter->next) + { + const gchar *retry_path = iter->data; + + menu_verbose ("retrying %s\n", retry_path); + + char *retry_basename = g_path_get_basename (retry_path); + + if (cached_dir_update_entry (dir, retry_basename, retry_path)) + retry_changes = TRUE; + + g_free (retry_basename); + } + + g_slist_free_full (dir->retry_later_desktop_entries, g_free); + dir->retry_later_desktop_entries = NULL; + + handled = retry_changes; + } else /* Try recursing */ { switch (event) @@ -584,8 +652,8 @@ if (handled) { - /* CHANGED events don't change the set of desktop entries */ - if (event == MENU_MONITOR_EVENT_CREATED || event == MENU_MONITOR_EVENT_DELETED) + /* CHANGED events don't change the set of desktop entries, unless it's the mimeinfo.cache file changing */ + if (retry_changes || (event == MENU_MONITOR_EVENT_CREATED || event == MENU_MONITOR_EVENT_DELETED)) { _entry_directory_list_empty_desktop_cache (); }
