[evolution-data-server] Bug 633122 - Maildir migration from old folder hierarchy to maildir++ hierarchy
- From: Chenthill Palanisamy <pchen src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug 633122 - Maildir migration from old folder hierarchy to maildir++ hierarchy
- Date: Fri, 29 Oct 2010 17:42:32 +0000 (UTC)
commit 1e032e852bdf468aa9a3ea27349334566152f4cc
Author: Chenthill Palanisamy <pchenthill novell com>
Date: Fri Oct 29 23:07:00 2010 +0530
Bug 633122 - Maildir migration from old folder hierarchy to maildir++ hierarchy
camel/providers/local/camel-maildir-store.c | 202 ++++++++++++++++++++++++++-
1 files changed, 200 insertions(+), 2 deletions(-)
---
diff --git a/camel/providers/local/camel-maildir-store.c b/camel/providers/local/camel-maildir-store.c
index 2cc56e0..a91ac60 100644
--- a/camel/providers/local/camel-maildir-store.c
+++ b/camel/providers/local/camel-maildir-store.c
@@ -54,6 +54,7 @@ static char *maildir_full_name_to_dir_name (const gchar *full_name);
static char *maildir_dir_name_to_fullname (const gchar *dir_name);
static gchar *maildir_get_full_path (CamelLocalStore *ls, const gchar *full_name);
static gchar *maildir_get_meta_path (CamelLocalStore *ls, const gchar *full_name, const gchar *ext);
+static void maildir_migrate_hierarchy (CamelMaildirStore *mstore, GCancellable *cancellable, GError **error);
/* This fixes up some historical cruft of names starting with "./" */
static const gchar *
@@ -453,10 +454,14 @@ maildir_full_name_to_dir_name (const gchar *full_name)
static char *
maildir_dir_name_to_fullname (const gchar *dir_name)
{
- gchar *full_name;
+ gchar *full_name, *skip_dots;
full_name = g_strdup (dir_name + 1);
- g_strdelimit (full_name, HIER_SEP, '/');
+ skip_dots = full_name;
+
+ while (*skip_dots == '.')
+ skip_dots++;
+ g_strdelimit (skip_dots, HIER_SEP, '/');
return full_name;
}
@@ -474,6 +479,7 @@ scan_dirs (CamelStore *store,
gint res = -1;
DIR *dir;
struct dirent *d;
+ gchar *meta_path = NULL;
folders = g_ptr_array_new ();
if (!strcmp (topfi->full_name, "."))
@@ -489,6 +495,10 @@ scan_dirs (CamelStore *store,
goto fail;
}
+ meta_path = maildir_get_meta_path ((CamelLocalStore *) store, ".", "maildir++");
+ if (!g_file_test (meta_path, G_FILE_TEST_EXISTS))
+ maildir_migrate_hierarchy ((CamelMaildirStore *) store, cancellable, error);
+
while ((d = readdir (dir))) {
gchar *full_name, *filename;
const gchar *short_name;
@@ -705,3 +715,191 @@ maildir_get_meta_path (CamelLocalStore *ls, const gchar *full_name, const gchar
return path;
}
+
+/* Migration from old to maildir++ hierarchy */
+
+struct _scan_node {
+ struct _scan_node *next;
+ struct _scan_node *prev;
+
+ CamelFolderInfo *fi;
+
+ dev_t dnode;
+ ino_t inode;
+};
+
+static guint scan_hash(gconstpointer d)
+{
+ const struct _scan_node *v = d;
+
+ return v->inode ^ v->dnode;
+}
+
+static gboolean scan_equal(gconstpointer a, gconstpointer b)
+{
+ const struct _scan_node *v1 = a, *v2 = b;
+
+ return v1->inode == v2->inode && v1->dnode == v2->dnode;
+}
+
+static void scan_free(gpointer k, gpointer v, gpointer d)
+{
+ g_free(k);
+}
+
+static gint
+scan_old_dir_info (CamelStore *store, CamelFolderInfo *topfi, GError **error)
+{
+ CamelDList queue = CAMEL_DLIST_INITIALISER(queue);
+ struct _scan_node *sn;
+ const gchar *root = ((CamelService *)store)->url->path;
+ gchar *tmp;
+ GHashTable *visited;
+ struct stat st;
+ gint res = -1;
+
+ visited = g_hash_table_new(scan_hash, scan_equal);
+
+ sn = g_malloc0 (sizeof(*sn));
+ sn->fi = topfi;
+ camel_dlist_addtail(&queue, (CamelDListNode *)sn);
+ g_hash_table_insert(visited, sn, sn);
+
+ while (!camel_dlist_empty(&queue)) {
+ gchar *name;
+ DIR *dir;
+ struct dirent *d;
+ CamelFolderInfo *last;
+
+ sn = (struct _scan_node *)camel_dlist_remhead(&queue);
+
+ last = (CamelFolderInfo *)&sn->fi->child;
+
+ if (!strcmp(sn->fi->full_name, "."))
+ name = g_strdup(root);
+ else
+ name = g_build_filename(root, sn->fi->full_name, NULL);
+
+ dir = opendir(name);
+ if (dir == NULL) {
+ g_free(name);
+ g_set_error (
+ error, G_IO_ERROR,
+ g_io_error_from_errno (errno),
+ _("Could not scan folder '%s': %s"),
+ root, g_strerror (errno));
+
+ goto fail;
+ }
+
+ while ((d = readdir(dir))) {
+ if (strcmp(d->d_name, "tmp") == 0
+ || strcmp(d->d_name, "cur") == 0
+ || strcmp(d->d_name, "new") == 0
+ || strcmp(d->d_name, ".#evolution") == 0
+ || strcmp(d->d_name, ".") == 0
+ || strcmp(d->d_name, "..") == 0)
+ continue;
+
+ tmp = g_build_filename(name, d->d_name, NULL);
+ if (stat(tmp, &st) == 0 && S_ISDIR(st.st_mode)) {
+ struct _scan_node in;
+
+ in.dnode = st.st_dev;
+ in.inode = st.st_ino;
+
+ /* see if we've visited already */
+ if (g_hash_table_lookup(visited, &in) == NULL) {
+ struct _scan_node *snew = g_malloc(sizeof(*snew));
+ gchar *full;
+ CamelFolderInfo *fi = NULL;
+
+ snew->dnode = in.dnode;
+ snew->inode = in.inode;
+
+ if (!strcmp(sn->fi->full_name, "."))
+ full = g_strdup(d->d_name);
+ else
+ full = g_strdup_printf("%s/%s", sn->fi->full_name, d->d_name);
+
+ fi = camel_folder_info_new ();
+ fi->full_name = full;
+ fi->name = g_strdup(d->d_name);
+ snew->fi = fi;
+
+ last->next = snew->fi;
+ last = snew->fi;
+ snew->fi->parent = sn->fi;
+
+ g_hash_table_insert(visited, snew, snew);
+ camel_dlist_addtail(&queue, (CamelDListNode *)snew);
+ }
+ }
+ g_free(tmp);
+ }
+ closedir(dir);
+ g_free (name);
+ }
+
+ res = 0;
+fail:
+ g_hash_table_foreach(visited, scan_free, NULL);
+ g_hash_table_destroy(visited);
+
+ return res;
+}
+
+static void
+maildir_rename_old_folder (CamelMaildirStore *mstore, CamelFolderInfo *fi, GCancellable *cancellable, GError **error)
+{
+ gchar *new_name = NULL;
+ CamelStoreClass *store_class;
+
+ new_name = maildir_full_name_to_dir_name (fi->full_name);
+
+ store_class = CAMEL_STORE_CLASS (camel_maildir_store_parent_class);
+ store_class->rename_folder_sync (
+ (CamelStore *)mstore, fi->full_name, new_name, cancellable, error);
+
+ g_free (new_name);
+}
+
+static void
+traverse_rename_folder_info (CamelMaildirStore *mstore, CamelFolderInfo *fi, GCancellable *cancellable, GError **error)
+{
+ if (fi != NULL) {
+ if (fi->child)
+ traverse_rename_folder_info (mstore, fi->child, cancellable, error);
+
+ if (strcmp (fi->full_name, ".") && ((!g_str_has_prefix (fi->full_name, ".") && (!fi->parent || !strcmp(fi->parent->full_name, "."))) ||
+ (fi->parent && strcmp (fi->parent->full_name, "."))))
+ maildir_rename_old_folder (mstore, fi, cancellable, error);
+
+ traverse_rename_folder_info (mstore, fi->next, cancellable, error);
+ }
+}
+
+static void
+maildir_migrate_hierarchy (CamelMaildirStore *mstore, GCancellable *cancellable, GError **error)
+{
+ CamelFolderInfo *topfi;
+ gchar *meta_path;
+
+ topfi = camel_folder_info_new ();
+ topfi->full_name = g_strdup (".");
+ topfi->name = g_strdup ("Inbox");
+
+ if (scan_old_dir_info ((CamelStore *) mstore, topfi, error) == -1) {
+ g_warning ("Failed to scan the old folder info \n");
+ camel_folder_info_free (topfi);
+ return;
+ }
+
+ traverse_rename_folder_info (mstore, topfi, cancellable, error);
+
+ meta_path = maildir_get_meta_path ((CamelLocalStore *) mstore, ".", "maildir++");
+ g_file_set_contents (meta_path, "maildir++", -1, NULL);
+
+ camel_folder_info_free (topfi);
+ g_free (meta_path);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]