[gtk+/gtk-2-24] recent-manager: Add migration to the new storage file location



commit 7825f01b2fb65dab94cb931780e958bc00448484
Author: Emmanuele Bassi <ebassi linux intel com>
Date:   Sat Oct 30 15:11:23 2010 +0100

    recent-manager: Add migration to the new storage file location
    
    The recently-used.xbel file location has been moved from $HOME to
    $XDG_DATA_DIR, to be compliant with the desktop bookmark specification
    and with other desktop environments following it.
    
    The effective change was done in gtk+-3, but we need a migration path
    for gtk+-2.
    
    The possible cases are:
    
      â?¢ the old file is not present, so we just switch to the new one;
      â?¢ the old file is present, but the new one is not; in this case
        we rename the old file to the new one.
      â?¢ both the old file and the new file are present; in this case,
        we try a simple merge of the contents and remove the old file.
    
    The merge is the (obviously) more expensive option, but it should only
    happen once.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=633242

 gtk/gtkrecentmanager.c |  139 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 135 insertions(+), 4 deletions(-)
---
diff --git a/gtk/gtkrecentmanager.c b/gtk/gtkrecentmanager.c
index b1b1e25..b343920 100644
--- a/gtk/gtkrecentmanager.c
+++ b/gtk/gtkrecentmanager.c
@@ -42,7 +42,7 @@
 #include "gtkalias.h"
 
 /* the file where we store the recently used items */
-#define GTK_RECENTLY_USED_FILE	".recently-used.xbel"
+#define GTK_RECENTLY_USED_FILE	"recently-used.xbel"
 
 /* return all items by default */
 #define DEFAULT_LIMIT	-1
@@ -468,6 +468,139 @@ gtk_recent_manager_monitor_changed (GFileMonitor      *monitor,
     }
 }
 
+/*
+ * get_default_recent_file:
+ *
+ * Retrieves the default storage file
+ *
+ * The default file is under XDG_DATA_HOME/recently-used.xbel but we also
+ * check if the old $HOME/.recently-used.xbel is still there, and rename it
+ * if needed.
+ *
+ * Return value: a newly allocated string with the new file
+ */
+static char *
+get_default_recent_file (void)
+{
+  char *old_file = g_build_filename (g_get_home_dir (),
+                                     "." GTK_RECENTLY_USED_FILE,
+                                     NULL);
+  char *new_file = g_build_filename (g_get_user_data_dir (),
+                                     GTK_RECENTLY_USED_FILE,
+                                     NULL);
+  GBookmarkFile *bf_old = NULL, *bf_new = NULL;
+  char **uris;
+  gsize n_uris, i;
+
+  /* simple case: the old file does not exist, so we just use the new one */
+  if (!g_file_test (old_file, G_FILE_TEST_EXISTS))
+    {
+      g_free (old_file);
+      return new_file;
+    }
+
+  /* less simple case: the old file still exists but the new one doesn't,
+   * so we rename the old one to the new one
+   */
+  if (!g_file_test (new_file, G_FILE_TEST_EXISTS))
+    {
+      if (g_rename (old_file, new_file) == -1)
+        filename_warning ("Unable to rename '%s': %s",
+                          old_file,
+                          g_strerror (errno));
+
+      g_free (old_file);
+      return new_file;
+    }
+
+  /* complex case: both the old file and the new file exist, so we do
+   * a preliminary parse pass and merge the contents, then remove the
+   * old file
+   */
+  bf_old = g_bookmark_file_new ();
+  if (!g_bookmark_file_load_from_file (bf_old, old_file, NULL))
+    goto unlink_and_return;
+
+  bf_new = g_bookmark_file_new ();
+  if (!g_bookmark_file_load_from_file (bf_new, new_file, NULL))
+    goto unlink_and_return;
+
+  uris = g_bookmark_file_get_uris (bf_old, &n_uris);
+  for (i = 0; i < n_uris; i++)
+    {
+      char *mime, *title, *description;
+      gboolean is_private;
+      char **apps;
+      gsize n_apps, j;
+
+      /* the new file always wins */
+      if (g_bookmark_file_has_item (bf_new, uris[i]))
+        continue;
+
+      mime = g_bookmark_file_get_mime_type (bf_old, uris[i], NULL);
+      title = g_bookmark_file_get_title (bf_old, uris[i], NULL);
+      description = g_bookmark_file_get_description (bf_old, uris[i], NULL);
+      is_private = g_bookmark_file_get_is_private (bf_old, uris[i], NULL);
+
+      g_bookmark_file_set_mime_type (bf_new, uris[i], mime);
+
+      if (title != NULL)
+        g_bookmark_file_set_title (bf_new, uris[i], title);
+
+      if (description != NULL)
+        g_bookmark_file_set_description (bf_new, uris[i], description);
+
+      g_free (mime);
+      g_free (title);
+      g_free (description);
+
+      g_bookmark_file_set_is_private (bf_new, uris[i], is_private);
+
+      apps = g_bookmark_file_get_applications (bf_old, uris[i], &n_apps, NULL);
+      for (j = 0; j < n_apps; j++)
+        {
+          char *exec;
+          guint count;
+          time_t stamp;
+
+          g_bookmark_file_get_app_info (bf_old, uris[i], apps[j],
+                                        &exec,
+                                        &count,
+                                        &stamp,
+                                        NULL);
+
+          g_bookmark_file_set_app_info (bf_new, uris[i], apps[j],
+                                        exec,
+                                        count,
+                                        stamp,
+                                        NULL);
+
+          g_free (exec);
+        }
+
+      g_strfreev (apps);
+    }
+
+  g_strfreev (uris);
+
+  /* we don't particularly care about errors here; if it fails then
+   * we start with a blank slate anyhow
+   */
+  g_bookmark_file_to_file (bf_new, new_file, NULL);
+
+unlink_and_return:
+  if (bf_old != NULL)
+    g_bookmark_file_free (bf_old);
+
+  if (bf_new != NULL)
+    g_bookmark_file_free (bf_new);
+
+  g_unlink (old_file);
+  g_free (old_file);
+
+  return new_file;
+}
+
 static void
 gtk_recent_manager_set_filename (GtkRecentManager *manager,
 				 const gchar      *filename)
@@ -508,9 +641,7 @@ gtk_recent_manager_set_filename (GtkRecentManager *manager,
   else
     {
       if (!filename || *filename == '\0')
-        priv->filename = g_build_filename (g_get_home_dir (),
-                                           GTK_RECENTLY_USED_FILE,
-                                           NULL);
+        priv->filename = get_default_recent_file ();
       else
         priv->filename = g_strdup (filename);
     }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]